Merge "Add a global-search column for last access."
diff --git a/Android.mk b/Android.mk
index d4d9a33..5f3327c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,6 +90,7 @@
core/java/android/bluetooth/IBluetoothA2dp.aidl \
core/java/android/bluetooth/IBluetoothCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
+ core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
core/java/android/content/IClipboard.aidl \
core/java/android/content/IContentService.aidl \
@@ -244,6 +245,7 @@
frameworks/base/core/java/android/app/Notification.aidl \
frameworks/base/core/java/android/app/PendingIntent.aidl \
frameworks/base/core/java/android/bluetooth/BluetoothDevice.aidl \
+ frameworks/base/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl \
frameworks/base/core/java/android/content/ComponentName.aidl \
frameworks/base/core/java/android/content/Intent.aidl \
frameworks/base/core/java/android/content/IntentSender.aidl \
@@ -364,6 +366,7 @@
-since ./frameworks/base/api/10.xml 10 \
-since ./frameworks/base/api/11.xml 11 \
-since ./frameworks/base/api/12.xml 12 \
+ -since ./frameworks/base/api/13.xml 13 \
-werror -hide 113 \
-overview $(LOCAL_PATH)/core/java/overview.html
@@ -414,6 +417,8 @@
resources/samples/NotePad "Note Pad" \
-samplecode $(sample_dir)/SampleSyncAdapter \
resources/samples/SampleSyncAdapter "Sample Sync Adapter" \
+ -samplecode $(sample_dir)/RandomMusicPlayer \
+ resources/samples/RandomMusicPlayer "Random Music Player" \
-samplecode $(sample_dir)/RenderScript \
resources/samples/RenderScript "RenderScript" \
-samplecode $(sample_dir)/SearchableDictionary \
diff --git a/api/13.xml b/api/13.xml
index 9af0640..2bfa04e 100644
--- a/api/13.xml
+++ b/api/13.xml
@@ -25290,7 +25290,7 @@
abstract="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<constructor name="ActivityGroup"
@@ -30614,6 +30614,17 @@
visibility="public"
>
</method>
+<method name="isDetached"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isHidden"
return="boolean"
abstract="false"
@@ -33935,7 +33946,7 @@
abstract="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<constructor name="LocalActivityManager"
@@ -37009,7 +37020,7 @@
abstract="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<constructor name="TabActivity"
@@ -61810,6 +61821,28 @@
visibility="public"
>
</field>
+<field name="FEATURE_SCREEN_LANDSCAPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.hardware.screen.landscape""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEATURE_SCREEN_PORTRAIT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.hardware.screen.portrait""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FEATURE_SENSOR_ACCELEROMETER"
type="java.lang.String"
transient="false"
@@ -148973,6 +149006,17 @@
visibility="public"
>
</field>
+<field name="TWEET_TRANSACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1599362900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</interface>
<interface name="IBinder.DeathRecipient"
abstract="true"
diff --git a/api/current.txt b/api/current.txt
index 885d9e8..5053859 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -190,6 +190,7 @@
field public static final int accountType = 16843407; // 0x101028f
field public static final int action = 16842797; // 0x101002d
field public static final int actionBarSize = 16843499; // 0x10102eb
+ field public static final int actionBarSplitStyle = 16843676; // 0x101039c
field public static final int actionBarStyle = 16843470; // 0x10102ce
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
@@ -218,6 +219,7 @@
field public static final int alertDialogIcon = 16843605; // 0x1010355
field public static final int alertDialogStyle = 16842845; // 0x101005d
field public static final int alertDialogTheme = 16843529; // 0x1010309
+ field public static final int alignmentMode = 16843642; // 0x101037a
field public static final int allContactsName = 16843468; // 0x10102cc
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -600,8 +602,10 @@
field public static final int layout_height = 16842997; // 0x10100f5
field public static final int layout_margin = 16842998; // 0x10100f6
field public static final int layout_marginBottom = 16843002; // 0x10100fa
+ field public static final int layout_marginEnd = 16843675; // 0x101039b
field public static final int layout_marginLeft = 16842999; // 0x10100f7
field public static final int layout_marginRight = 16843001; // 0x10100f9
+ field public static final int layout_marginStart = 16843674; // 0x101039a
field public static final int layout_marginTop = 16843000; // 0x10100f8
field public static final int layout_row = 16843643; // 0x101037b
field public static final int layout_rowSpan = 16843644; // 0x101037c
@@ -627,6 +631,8 @@
field public static final int listDividerAlertDialog = 16843525; // 0x1010305
field public static final int listPopupWindowStyle = 16843519; // 0x10102ff
field public static final int listPreferredItemHeight = 16842829; // 0x101004d
+ field public static final int listPreferredItemHeightLarge = 16843670; // 0x1010396
+ field public static final int listPreferredItemHeightSmall = 16843671; // 0x1010397
field public static final int listSelector = 16843003; // 0x10100fb
field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
field public static final int listViewStyle = 16842868; // 0x1010074
@@ -636,7 +642,6 @@
field public static final int loopViews = 16843527; // 0x1010307
field public static final int manageSpaceActivity = 16842756; // 0x1010004
field public static final int mapViewStyle = 16842890; // 0x101008a
- field public static final int marginsIncludedInAlignment = 16843642; // 0x101037a
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int max = 16843062; // 0x1010136
field public static final int maxDate = 16843584; // 0x1010340
@@ -694,8 +699,10 @@
field public static final int packageNames = 16843651; // 0x1010383
field public static final int padding = 16842965; // 0x10100d5
field public static final int paddingBottom = 16842969; // 0x10100d9
+ field public static final int paddingEnd = 16843673; // 0x1010399
field public static final int paddingLeft = 16842966; // 0x10100d6
field public static final int paddingRight = 16842968; // 0x10100d8
+ field public static final int paddingStart = 16843672; // 0x1010398
field public static final int paddingTop = 16842967; // 0x10100d7
field public static final int panelBackground = 16842846; // 0x101005e
field public static final int panelColorBackground = 16842849; // 0x1010061
@@ -968,6 +975,7 @@
field public static final int textColorTertiary = 16843282; // 0x1010212
field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
field public static final int textCursorDrawable = 16843618; // 0x1010362
+ field public static final int textDirection = 16843677; // 0x101039d
field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -1374,6 +1382,7 @@
field public static final int config_longAnimTime = 17694722; // 0x10e0002
field public static final int config_mediumAnimTime = 17694721; // 0x10e0001
field public static final int config_shortAnimTime = 17694720; // 0x10e0000
+ field public static final int status_bar_notification_info_maxnum = 17694723; // 0x10e0003
}
public static final class R.interpolator {
@@ -1460,6 +1469,7 @@
field public static final int search_go = 17039372; // 0x104000c
field public static final int selectAll = 17039373; // 0x104000d
field public static final int selectTextMode = 17039382; // 0x1040016
+ field public static final int status_bar_notification_info_overflow = 17039383; // 0x1040017
field public static final int unknownName = 17039374; // 0x104000e
field public static final int untitled = 17039375; // 0x104000f
field public static final int yes = 17039379; // 0x1040013
@@ -3361,6 +3371,7 @@
method public void send(android.content.Context, int, android.content.Intent) throws android.app.PendingIntent.CanceledException;
method public void send(int, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler) throws android.app.PendingIntent.CanceledException;
+ method public void send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler, java.lang.String) throws android.app.PendingIntent.CanceledException;
method public static void writePendingIntentOrNullToParcel(android.app.PendingIntent, android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
@@ -5288,6 +5299,7 @@
method public java.lang.String getTargetPackage();
method public static android.content.IntentSender readIntentSenderOrNullFromParcel(android.os.Parcel);
method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler) throws android.content.IntentSender.SendIntentException;
+ method public void sendIntent(android.content.Context, int, android.content.Intent, android.content.IntentSender.OnFinished, android.os.Handler, java.lang.String) throws android.content.IntentSender.SendIntentException;
method public static void writeIntentSenderOrNullToParcel(android.content.IntentSender, android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
@@ -5807,6 +5819,7 @@
method public abstract void setInstallerPackageName(java.lang.String, java.lang.String);
field public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0; // 0x0
field public static final int COMPONENT_ENABLED_STATE_DISABLED = 2; // 0x2
+ field public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // 0x3
field public static final int COMPONENT_ENABLED_STATE_ENABLED = 1; // 0x1
field public static final int DONT_KILL_APP = 1; // 0x1
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
@@ -5887,6 +5900,7 @@
field public long codeSize;
field public long dataSize;
field public long externalCacheSize;
+ field public long externalCodeSize;
field public long externalDataSize;
field public long externalMediaSize;
field public long externalObbSize;
@@ -7411,6 +7425,7 @@
method public static final android.graphics.Bitmap.CompressFormat[] values();
enum_constant public static final android.graphics.Bitmap.CompressFormat JPEG;
enum_constant public static final android.graphics.Bitmap.CompressFormat PNG;
+ enum_constant public static final android.graphics.Bitmap.CompressFormat WEBP;
}
public static final class Bitmap.Config extends java.lang.Enum {
@@ -8358,6 +8373,7 @@
public class SurfaceTexture {
ctor public SurfaceTexture(int);
+ ctor public SurfaceTexture(int, boolean);
method public long getTimestamp();
method public void getTransformMatrix(float[]);
method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
@@ -9386,6 +9402,7 @@
method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
method public void onUpdateSelection(int, int, int, int, int, int);
+ method public void onViewClicked(boolean);
method public void onWindowHidden();
method public void onWindowShown();
method public void requestHideSelf(int);
@@ -9429,6 +9446,7 @@
method public void updateCursor(android.graphics.Rect);
method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
method public void updateSelection(int, int, int, int, int, int);
+ method public void viewClicked(boolean);
}
public static final class InputMethodService.Insets {
@@ -10427,6 +10445,16 @@
method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
}
+ public class Metadata {
+ method public boolean getBoolean(int);
+ method public boolean has(int);
+ method public java.util.Set<java.lang.Integer> keySet();
+ field public static final int PAUSE_AVAILABLE = 1; // 0x1
+ field public static final int SEEK_AVAILABLE = 4; // 0x4
+ field public static final int SEEK_BACKWARD_AVAILABLE = 2; // 0x2
+ field public static final int SEEK_FORWARD_AVAILABLE = 3; // 0x3
+ }
+
public class Ringtone {
method public int getStreamType();
method public java.lang.String getTitle(android.content.Context);
@@ -11219,7 +11247,8 @@
method public static long getUidUdpRxPackets(int);
method public static long getUidUdpTxBytes(int);
method public static long getUidUdpTxPackets(int);
- method public static void setThreadStatsTag(java.lang.String);
+ method public static void setThreadStatsTag(int);
+ method public static deprecated void setThreadStatsTag(java.lang.String);
method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
field public static final int UNSUPPORTED = -1; // 0xffffffff
@@ -11425,11 +11454,14 @@
}
public class SslError {
- ctor public SslError(int, android.net.http.SslCertificate);
- ctor public SslError(int, java.security.cert.X509Certificate);
+ ctor public deprecated SslError(int, android.net.http.SslCertificate);
+ ctor public deprecated SslError(int, java.security.cert.X509Certificate);
+ ctor public SslError(int, android.net.http.SslCertificate, java.lang.String);
+ ctor public SslError(int, java.security.cert.X509Certificate, java.lang.String);
method public boolean addError(int);
method public android.net.http.SslCertificate getCertificate();
method public int getPrimaryError();
+ method public java.lang.String getUrl();
method public boolean hasError(int);
field public static final int SSL_EXPIRED = 1; // 0x1
field public static final int SSL_IDMISMATCH = 2; // 0x2
@@ -15260,12 +15292,14 @@
public final class ContactsContract {
ctor public ContactsContract();
+ field public static final java.lang.String ALLOW_PROFILE = "allow_profile";
field public static final java.lang.String AUTHORITY = "com.android.contacts";
field public static final android.net.Uri AUTHORITY_URI;
field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory";
- field public static final java.lang.String INCLUDE_PROFILE = "include_profile";
field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
+ field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
+ field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
}
public static final class ContactsContract.AggregationExceptions implements android.provider.BaseColumns {
@@ -15608,6 +15642,15 @@
protected static abstract interface ContactsContract.DataColumnsWithJoins implements android.provider.BaseColumns android.provider.ContactsContract.ContactNameColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns android.provider.ContactsContract.DataColumns android.provider.ContactsContract.RawContactsColumns android.provider.ContactsContract.StatusColumns {
}
+ public static final class ContactsContract.DataUsageFeedback {
+ ctor public ContactsContract.DataUsageFeedback();
+ field public static final android.net.Uri FEEDBACK_URI;
+ field public static final java.lang.String USAGE_TYPE = "type";
+ field public static final java.lang.String USAGE_TYPE_CALL = "call";
+ field public static final java.lang.String USAGE_TYPE_LONG_TEXT = "long_text";
+ field public static final java.lang.String USAGE_TYPE_SHORT_TEXT = "short_text";
+ }
+
public static final class ContactsContract.Directory implements android.provider.BaseColumns {
method public static void notifyDirectoryChange(android.content.ContentResolver);
field public static final java.lang.String ACCOUNT_NAME = "accountName";
@@ -16648,10 +16691,25 @@
method public static android.renderscript.Element F32_3(android.renderscript.RenderScript);
method public static android.renderscript.Element F32_4(android.renderscript.RenderScript);
method public static android.renderscript.Element F64(android.renderscript.RenderScript);
+ method public static android.renderscript.Element F64_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element F64_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element F64_4(android.renderscript.RenderScript);
method public static android.renderscript.Element I16(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I16_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I16_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I16_4(android.renderscript.RenderScript);
method public static android.renderscript.Element I32(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I32_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I32_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I32_4(android.renderscript.RenderScript);
method public static android.renderscript.Element I64(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I64_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I64_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I64_4(android.renderscript.RenderScript);
method public static android.renderscript.Element I8(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I8_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I8_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element I8_4(android.renderscript.RenderScript);
method public static android.renderscript.Element MATRIX4X4(android.renderscript.RenderScript);
method public static android.renderscript.Element MATRIX_2X2(android.renderscript.RenderScript);
method public static android.renderscript.Element MATRIX_3X3(android.renderscript.RenderScript);
@@ -16670,12 +16728,24 @@
method public static android.renderscript.Element SCRIPT(android.renderscript.RenderScript);
method public static android.renderscript.Element TYPE(android.renderscript.RenderScript);
method public static android.renderscript.Element U16(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U16_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U16_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U16_4(android.renderscript.RenderScript);
method public static android.renderscript.Element U32(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U32_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U32_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U32_4(android.renderscript.RenderScript);
method public static android.renderscript.Element U64(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U64_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U64_3(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U64_4(android.renderscript.RenderScript);
method public static android.renderscript.Element U8(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U8_2(android.renderscript.RenderScript);
+ method public static android.renderscript.Element U8_3(android.renderscript.RenderScript);
method public static android.renderscript.Element U8_4(android.renderscript.RenderScript);
method public static android.renderscript.Element createPixel(android.renderscript.RenderScript, android.renderscript.Element.DataType, android.renderscript.Element.DataKind);
method public static android.renderscript.Element createVector(android.renderscript.RenderScript, android.renderscript.Element.DataType, int);
+ method public boolean isCompatible(android.renderscript.Element);
method public boolean isComplex();
}
@@ -16738,6 +16808,9 @@
method public void addF32(android.renderscript.Float3);
method public void addF32(android.renderscript.Float4);
method public void addF64(double);
+ method public void addF64(android.renderscript.Double2);
+ method public void addF64(android.renderscript.Double3);
+ method public void addF64(android.renderscript.Double4);
method public void addI16(short);
method public void addI16(android.renderscript.Short2);
method public void addI16(android.renderscript.Short3);
@@ -16747,6 +16820,9 @@
method public void addI32(android.renderscript.Int3);
method public void addI32(android.renderscript.Int4);
method public void addI64(long);
+ method public void addI64(android.renderscript.Long2);
+ method public void addI64(android.renderscript.Long3);
+ method public void addI64(android.renderscript.Long4);
method public void addI8(byte);
method public void addI8(android.renderscript.Byte2);
method public void addI8(android.renderscript.Byte3);
@@ -16764,6 +16840,9 @@
method public void addU32(android.renderscript.Long3);
method public void addU32(android.renderscript.Long4);
method public void addU64(long);
+ method public void addU64(android.renderscript.Long2);
+ method public void addU64(android.renderscript.Long3);
+ method public void addU64(android.renderscript.Long4);
method public void addU8(short);
method public void addU8(android.renderscript.Short2);
method public void addU8(android.renderscript.Short3);
@@ -17374,9 +17453,12 @@
enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_X;
enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_Y;
enum_constant public static final android.renderscript.Type.CubemapFace NEGATIVE_Z;
- enum_constant public static final android.renderscript.Type.CubemapFace POSITVE_X;
- enum_constant public static final android.renderscript.Type.CubemapFace POSITVE_Y;
- enum_constant public static final android.renderscript.Type.CubemapFace POSITVE_Z;
+ enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_X;
+ enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_Y;
+ enum_constant public static final android.renderscript.Type.CubemapFace POSITIVE_Z;
+ enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_X;
+ enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_Y;
+ enum_constant public static final deprecated android.renderscript.Type.CubemapFace POSITVE_Z;
}
}
@@ -17425,7 +17507,7 @@
public final class KeyChain {
ctor public KeyChain();
- method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int);
+ method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException;
}
@@ -17659,6 +17741,7 @@
field public static final java.lang.String KEY_PARAM_STREAM = "streamType";
field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId";
field public static final java.lang.String KEY_PARAM_VOLUME = "volume";
+ field public static final java.lang.String SERVICE_META_DATA = "android.speech.tts";
}
public static class TextToSpeech.EngineInfo {
@@ -21354,7 +21437,6 @@
field public static final int AXIS_Y = 1; // 0x1
field public static final int AXIS_Z = 11; // 0xb
field public static final int BUTTON_BACK = 8; // 0x8
- field public static final int BUTTON_ERASER = 32; // 0x20
field public static final int BUTTON_FORWARD = 16; // 0x10
field public static final int BUTTON_PRIMARY = 1; // 0x1
field public static final int BUTTON_SECONDARY = 2; // 0x2
@@ -21578,6 +21660,7 @@
method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
method public boolean isAvailable();
method protected final void onDraw(android.graphics.Canvas);
+ method public void setOpaque(boolean);
method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
}
@@ -21585,6 +21668,7 @@
method public abstract void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
method public abstract void onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
method public abstract void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+ method public abstract void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
}
public class TouchDelegate {
@@ -21647,7 +21731,10 @@
method public void dispatchDisplayHint(int);
method public boolean dispatchDragEvent(android.view.DragEvent);
method protected void dispatchDraw(android.graphics.Canvas);
+ method protected boolean dispatchGenericFocusedEvent(android.view.MotionEvent);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
+ method protected boolean dispatchGenericPointerEvent(android.view.MotionEvent);
+ method protected boolean dispatchHoverEvent(android.view.MotionEvent);
method public boolean dispatchKeyEvent(android.view.KeyEvent);
method public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
@@ -21798,6 +21885,7 @@
method public boolean isHovered();
method public boolean isInEditMode();
method public boolean isInTouchMode();
+ method protected static boolean isLayoutDirectionRtl(java.util.Locale);
method public boolean isLayoutRequested();
method public boolean isLongClickable();
method public boolean isOpaque();
@@ -21835,6 +21923,7 @@
method public void onFinishTemporaryDetach();
method protected void onFocusChanged(boolean, int, android.graphics.Rect);
method public boolean onGenericMotionEvent(android.view.MotionEvent);
+ method public void onHoverChanged(boolean);
method public boolean onHoverEvent(android.view.MotionEvent);
method public void onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo);
@@ -21882,8 +21971,10 @@
method public void requestLayout();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
+ method protected void resetResolvedTextDirection();
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
+ method protected void resolveTextDirection();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
@@ -21933,6 +22024,7 @@
method public void setOnDragListener(android.view.View.OnDragListener);
method public void setOnFocusChangeListener(android.view.View.OnFocusChangeListener);
method public void setOnGenericMotionListener(android.view.View.OnGenericMotionListener);
+ method public void setOnHoverListener(android.view.View.OnHoverListener);
method public void setOnKeyListener(android.view.View.OnKeyListener);
method public void setOnLongClickListener(android.view.View.OnLongClickListener);
method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
@@ -21981,6 +22073,8 @@
method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
method public boolean willNotCacheDrawing();
method public boolean willNotDraw();
+ field public static android.util.Property ALPHA;
+ field protected static int DEFAULT_TEXT_DIRECTION;
field public static final int DRAWING_CACHE_QUALITY_AUTO = 0; // 0x0
field public static final int DRAWING_CACHE_QUALITY_HIGH = 1048576; // 0x100000
field public static final int DRAWING_CACHE_QUALITY_LOW = 524288; // 0x80000
@@ -22111,6 +22205,10 @@
method public abstract boolean onGenericMotion(android.view.View, android.view.MotionEvent);
}
+ public static abstract interface View.OnHoverListener {
+ method public abstract boolean onHover(android.view.View, android.view.MotionEvent);
+ }
+
public static abstract interface View.OnKeyListener {
method public abstract boolean onKey(android.view.View, int, android.view.KeyEvent);
}
@@ -22166,6 +22264,7 @@
method public static deprecated int getTouchSlop();
method public static deprecated int getWindowTouchSlop();
method public static long getZoomControlsTimeout();
+ method public boolean hasPermanentMenuKey();
}
public class ViewDebug {
@@ -22281,6 +22380,7 @@
method protected void measureChildren(int, int);
method public final void offsetDescendantRectToMyCoords(android.view.View, android.graphics.Rect);
method public final void offsetRectIntoDescendantCoords(android.view.View, android.graphics.Rect);
+ method public boolean onInterceptHoverEvent(android.view.MotionEvent);
method public boolean onInterceptTouchEvent(android.view.MotionEvent);
method protected abstract void onLayout(boolean, int, int, int, int);
method protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
@@ -22299,6 +22399,7 @@
method public void requestDisallowInterceptTouchEvent(boolean);
method public boolean requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
method public void requestTransparentRegion(android.view.View);
+ method protected void resetLayoutDirectionResolution();
method public void scheduleLayoutAnimation();
method public void setAddStatesFromChildren(boolean);
method public void setAlwaysDrawnWithCacheEnabled(boolean);
@@ -22765,8 +22866,10 @@
field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
+ field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+ field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
}
@@ -22815,6 +22918,7 @@
method public boolean isFocused();
method public boolean isLongClickable();
method public boolean isPassword();
+ method public boolean isScrollable();
method public boolean isSelected();
method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
method public static android.view.accessibility.AccessibilityNodeInfo obtain();
@@ -22834,6 +22938,7 @@
method public void setPackageName(java.lang.CharSequence);
method public void setParent(android.view.View);
method public void setPassword(boolean);
+ method public void setScrollable(boolean);
method public void setSelected(boolean);
method public void setSource(android.view.View);
method public void setText(java.lang.CharSequence);
@@ -22855,13 +22960,17 @@
method public int getItemCount();
method public android.os.Parcelable getParcelableData();
method public int getRemovedCount();
+ method public int getScrollX();
+ method public int getScrollY();
method public android.view.accessibility.AccessibilityNodeInfo getSource();
method public java.util.List<java.lang.CharSequence> getText();
+ method public int getToIndex();
method public int getWindowId();
method public boolean isChecked();
method public boolean isEnabled();
method public boolean isFullScreen();
method public boolean isPassword();
+ method public boolean isScrollable();
method public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
method public static android.view.accessibility.AccessibilityRecord obtain();
method public void recycle();
@@ -22878,7 +22987,11 @@
method public void setParcelableData(android.os.Parcelable);
method public void setPassword(boolean);
method public void setRemovedCount(int);
+ method public void setScrollX(int);
+ method public void setScrollY(int);
+ method public void setScrollable(boolean);
method public void setSource(android.view.View);
+ method public void setToIndex(int);
}
}
@@ -23411,6 +23524,7 @@
method public void updateCursor(android.view.View, int, int, int, int);
method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
method public void updateSelection(android.view.View, int, int, int, int);
+ method public void viewClicked(android.view.View);
field public static final int HIDE_IMPLICIT_ONLY = 1; // 0x1
field public static final int HIDE_NOT_ALWAYS = 2; // 0x2
field public static final int RESULT_HIDDEN = 3; // 0x3
@@ -23431,6 +23545,7 @@
method public abstract void updateCursor(android.graphics.Rect);
method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
method public abstract void updateSelection(int, int, int, int, int, int);
+ method public abstract void viewClicked(boolean);
}
public static abstract interface InputMethodSession.EventCallback {
@@ -23718,7 +23833,8 @@
method public boolean getSavePassword();
method public synchronized java.lang.String getSerifFontFamily();
method public synchronized java.lang.String getStandardFontFamily();
- method public synchronized android.webkit.WebSettings.TextSize getTextSize();
+ method public deprecated synchronized android.webkit.WebSettings.TextSize getTextSize();
+ method public synchronized int getTextZoom();
method public deprecated synchronized boolean getUseDoubleTree();
method public deprecated boolean getUseWebViewBackgroundForOverscrollBackground();
method public synchronized boolean getUseWideViewPort();
@@ -23768,7 +23884,8 @@
method public synchronized void setStandardFontFamily(java.lang.String);
method public synchronized void setSupportMultipleWindows(boolean);
method public void setSupportZoom(boolean);
- method public synchronized void setTextSize(android.webkit.WebSettings.TextSize);
+ method public deprecated synchronized void setTextSize(android.webkit.WebSettings.TextSize);
+ method public synchronized void setTextZoom(int);
method public deprecated synchronized void setUseDoubleTree(boolean);
method public deprecated void setUseWebViewBackgroundForOverscrollBackground(boolean);
method public synchronized void setUseWideViewPort(boolean);
@@ -23807,7 +23924,7 @@
enum_constant public static final android.webkit.WebSettings.RenderPriority NORMAL;
}
- public static final class WebSettings.TextSize extends java.lang.Enum {
+ public static final deprecated class WebSettings.TextSize extends java.lang.Enum {
method public static android.webkit.WebSettings.TextSize valueOf(java.lang.String);
method public static final android.webkit.WebSettings.TextSize[] values();
enum_constant public static final android.webkit.WebSettings.TextSize LARGER;
@@ -24778,21 +24895,23 @@
ctor public GridLayout(android.content.Context);
ctor public GridLayout(android.content.Context, android.util.AttributeSet, int);
ctor public GridLayout(android.content.Context, android.util.AttributeSet);
+ method public int getAlignmentMode();
method public int getColumnCount();
- method public boolean getMarginsIncludedInAlignment();
method public int getOrientation();
method public int getRowCount();
method public boolean getUseDefaultMargins();
method public boolean isColumnOrderPreserved();
method public boolean isRowOrderPreserved();
method protected void onLayout(boolean, int, int, int, int);
+ method public void setAlignmentMode(int);
method public void setColumnCount(int);
method public void setColumnOrderPreserved(boolean);
- method public void setMarginsIncludedInAlignment(boolean);
method public void setOrientation(int);
method public void setRowCount(int);
method public void setRowOrderPreserved(boolean);
method public void setUseDefaultMargins(boolean);
+ field public static final int ALIGN_BOUNDS = 0; // 0x0
+ field public static final int ALIGN_MARGINS = 1; // 0x1
field public static final android.widget.GridLayout.Alignment BASELINE;
field public static final android.widget.GridLayout.Alignment BOTTOM;
field public static final android.widget.GridLayout.Alignment CENTER;
@@ -24806,9 +24925,6 @@
}
public static abstract class GridLayout.Alignment {
- ctor public GridLayout.Alignment();
- method public abstract int getAlignmentValue(android.view.View, int, int);
- method public int getSizeInCell(android.view.View, int, int, int);
}
public static class GridLayout.Group {
@@ -25220,10 +25336,16 @@
method public void dismiss();
method public android.view.Menu getMenu();
method public android.view.MenuInflater getMenuInflater();
+ method public void inflate(int);
+ method public void setOnDismissListener(android.widget.PopupMenu.OnDismissListener);
method public void setOnMenuItemClickListener(android.widget.PopupMenu.OnMenuItemClickListener);
method public void show();
}
+ public static abstract interface PopupMenu.OnDismissListener {
+ method public abstract void onDismiss(android.widget.PopupMenu);
+ }
+
public static abstract interface PopupMenu.OnMenuItemClickListener {
method public abstract boolean onMenuItemClick(android.view.MenuItem);
}
@@ -25946,6 +26068,7 @@
method protected void onTextChanged(java.lang.CharSequence, int, int, int);
method public boolean onTextContextMenuItem(int);
method public void removeTextChangedListener(android.text.TextWatcher);
+ method protected void resetLayoutDirectionResolution();
method public final void setAutoLinkMask(int);
method public void setCompoundDrawablePadding(int);
method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
@@ -26973,9 +27096,7 @@
public final class FilePermission extends java.security.Permission implements java.io.Serializable {
ctor public FilePermission(java.lang.String, java.lang.String);
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
@@ -29734,8 +29855,8 @@
ctor public DatagramSocket(java.net.SocketAddress) throws java.net.SocketException;
method public void bind(java.net.SocketAddress) throws java.net.SocketException;
method public void close();
- method public void connect(java.net.InetAddress, int);
method public void connect(java.net.SocketAddress) throws java.net.SocketException;
+ method public void connect(java.net.InetAddress, int);
method public void disconnect();
method public boolean getBroadcast() throws java.net.SocketException;
method public java.nio.channels.DatagramChannel getChannel();
@@ -30223,9 +30344,7 @@
public final class SocketPermission extends java.security.Permission implements java.io.Serializable {
ctor public SocketPermission(java.lang.String, java.lang.String);
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
@@ -31232,9 +31351,7 @@
public final class AllPermission extends java.security.Permission {
ctor public AllPermission(java.lang.String, java.lang.String);
ctor public AllPermission();
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
@@ -31248,9 +31365,7 @@
public abstract class BasicPermission extends java.security.Permission implements java.io.Serializable {
ctor public BasicPermission(java.lang.String);
ctor public BasicPermission(java.lang.String, java.lang.String);
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
@@ -31613,10 +31728,8 @@
public abstract class Permission implements java.security.Guard java.io.Serializable {
ctor public Permission(java.lang.String);
method public void checkGuard(java.lang.Object) throws java.lang.SecurityException;
- method public abstract boolean equals(java.lang.Object);
method public abstract java.lang.String getActions();
method public final java.lang.String getName();
- method public abstract int hashCode();
method public abstract boolean implies(java.security.Permission);
method public java.security.PermissionCollection newPermissionCollection();
}
@@ -31873,13 +31986,11 @@
public final class UnresolvedPermission extends java.security.Permission implements java.io.Serializable {
ctor public UnresolvedPermission(java.lang.String, java.lang.String, java.lang.String, java.security.cert.Certificate[]);
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
method public java.lang.String getUnresolvedActions();
method public java.security.cert.Certificate[] getUnresolvedCerts();
method public java.lang.String getUnresolvedName();
method public java.lang.String getUnresolvedType();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
@@ -39395,11 +39506,9 @@
public final class PrivateCredentialPermission extends java.security.Permission {
ctor public PrivateCredentialPermission(java.lang.String, java.lang.String);
- method public boolean equals(java.lang.Object);
method public java.lang.String getActions();
method public java.lang.String getCredentialClass();
method public java.lang.String[][] getPrincipals();
- method public int hashCode();
method public boolean implies(java.security.Permission);
}
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
index 788b686..16e0505 100644
--- a/build/phone-hdpi-512-dalvik-heap.mk
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -19,5 +19,5 @@
PRODUCT_PROPERTY_OVERRIDES += \
dalvik.vm.heapstartsize=5m \
- dalvik.vm.heapgrowthlimit=32m \
+ dalvik.vm.heapgrowthlimit=48m \
dalvik.vm.heapsize=128m
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 424b70a..479b70a 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -33,6 +33,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.util.AndroidException;
import android.view.IWindowManager;
@@ -199,6 +200,10 @@
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else if (opt.equals("--grant-write-uri-permission")) {
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ } else if (opt.equals("--exclude-stopped-packages")) {
+ intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
+ } else if (opt.equals("--include-stopped-packages")) {
+ intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
} else if (opt.equals("--debug-log-resolution")) {
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
} else if (opt.equals("--activity-brought-to-front")) {
@@ -227,6 +232,10 @@
intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
} else if (opt.equals("--activity-single-top")) {
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ } else if (opt.equals("--activity-clear-task")) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ } else if (opt.equals("--activity-task-on-home")) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
} else if (opt.equals("--receiver-registered-only")) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
} else if (opt.equals("--receiver-replace-pending")) {
@@ -400,7 +409,8 @@
argKey = nextArgRequired();
argValue = nextArgRequired();
args.putString(argKey, argValue);
- } else if (opt.equals("--no_window_animation")) {
+ } else if (opt.equals("--no_window_animation")
+ || opt.equals("--no-window-animation")) {
no_window_animation = true;
} else {
System.err.println("Error: Unknown option: " + opt);
@@ -440,15 +450,43 @@
}
}
+ static void removeWallOption() {
+ String props = SystemProperties.get("dalvik.vm.extra-opts");
+ if (props != null && props.contains("-Xprofile:wallclock")) {
+ props = props.replace("-Xprofile:wallclock", "");
+ props = props.trim();
+ SystemProperties.set("dalvik.vm.extra-opts", props);
+ }
+ }
+
private void runProfile() throws Exception {
String profileFile = null;
boolean start = false;
- String process = nextArgRequired();
- ParcelFileDescriptor fd = null;
-
+ boolean wall = false;
+
+ String process = null;
+
String cmd = nextArgRequired();
if ("start".equals(cmd)) {
start = true;
+ wall = "--wall".equals(nextOption());
+ process = nextArgRequired();
+ } else if ("stop".equals(cmd)) {
+ process = nextArgRequired();
+ } else {
+ // Compatibility with old syntax: process is specified first.
+ process = cmd;
+ cmd = nextArgRequired();
+ if ("start".equals(cmd)) {
+ start = true;
+ } else if (!"stop".equals(cmd)) {
+ throw new IllegalArgumentException("Profile command " + process + " not valid");
+ }
+ }
+
+ ParcelFileDescriptor fd = null;
+
+ if (start) {
profileFile = nextArgRequired();
try {
fd = ParcelFileDescriptor.open(
@@ -460,12 +498,27 @@
System.err.println("Error: Unable to open file: " + profileFile);
return;
}
- } else if (!"stop".equals(cmd)) {
- throw new IllegalArgumentException("Profile command " + cmd + " not valid");
}
- if (!mAm.profileControl(process, start, profileFile, fd)) {
- throw new AndroidException("PROFILE FAILED on process " + process);
+ try {
+ if (wall) {
+ // XXX doesn't work -- this needs to be set before booting.
+ String props = SystemProperties.get("dalvik.vm.extra-opts");
+ if (props == null || !props.contains("-Xprofile:wallclock")) {
+ props = props + " -Xprofile:wallclock";
+ //SystemProperties.set("dalvik.vm.extra-opts", props);
+ }
+ } else if (start) {
+ //removeWallOption();
+ }
+ if (!mAm.profileControl(process, start, profileFile, fd)) {
+ wall = false;
+ throw new AndroidException("PROFILE FAILED on process " + process);
+ }
+ } finally {
+ if (!wall) {
+ //removeWallOption();
+ }
}
}
@@ -1012,62 +1065,76 @@
private static void showUsage() {
System.err.println(
"usage: am [subcommand] [options]\n" +
+ "usage: am start [-D] [-W] <INTENT>\n" +
+ " am startservice <INTENT>\n" +
+ " am force-stop <PACKAGE>\n" +
+ " am broadcast <INTENT>\n" +
+ " am instrument [-r] [-e <NAME> <VALUE>] [-p] [-w]\n" +
+ " [--no-window-animation] <COMPONENT>\n" +
+ " am profile start <PROCESS> <FILE>\n" +
+ " am profile stop <PROCESS>\n" +
+ " am dumpheap [flags] <PROCESS> <FILE>\n" +
+ " am monitor [--gdb <port>]\n" +
+ " am screen-compat [on|off] <PACKAGE>\n" +
+ " am display-size [reset|MxN]\n" +
"\n" +
- " start an Activity: am start [-D] [-W] <INTENT>\n" +
- " -D: enable debugging\n" +
- " -W: wait for launch to complete\n" +
+ "am start: start an Activity. Options are:\n" +
+ " -D: enable debugging\n" +
+ " -W: wait for launch to complete\n" +
"\n" +
- " start a Service: am startservice <INTENT>\n" +
+ "am startservice: start a Service.\n" +
"\n" +
- " force stop everything associated with a package: force-stop <package>\n" +
+ "am force-stop: force stop everything associated with <PACKAGE>.\n" +
"\n" +
- " send a broadcast Intent: am broadcast <INTENT>\n" +
+ "am broadcast: send a broadcast Intent.\n" +
"\n" +
- " start an Instrumentation: am instrument [flags] <COMPONENT>\n" +
- " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)\n" +
- " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>\n" +
- " -p <FILE>: write profiling data to <FILE>\n" +
- " -w: wait for instrumentation to finish before returning\n" +
+ "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
+ " is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:\n" +
+ " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
+ " [-e perf true] to generate raw output for performance measurements.\n" +
+ " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
+ " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
+ " -p <FILE>: write profiling data to <FILE>\n" +
+ " -w: wait for instrumentation to finish before returning. Required for\n" +
+ " test runners.\n" +
+ " --no-window-animation: turn off window animations will running.\n" +
"\n" +
- " run a test package against an application: am instrument [flags] <TEST_PACKAGE>/<RUNNER_CLASS>\n" +
- " -e <testrunner_flag> <testrunner_value> [,<testrunner_value>]\n" +
- " -w wait for the test to finish (required)\n" +
- " -r use with -e perf true to generate raw output for performance measurements\n" +
+ "am profile: start and stop profiler on a process.\n" +
"\n" +
- " start profiling: am profile <PROCESS> start <FILE>\n" +
- " stop profiling: am profile <PROCESS> stop\n" +
- " dump heap: am dumpheap [flags] <PROCESS> <FILE>\n" +
- " -n: dump native heap instead of managed heap\n" +
+ "am dumpheap: dump the heap of a process. Options are:\n" +
+ " -n: dump native heap instead of managed heap\n" +
"\n" +
- " start monitoring: am monitor [--gdb <port>]\n" +
- " --gdb: start gdbserv on the given port at crash/ANR\n" +
+ "am monitor: start monitoring for crashes or ANRs.\n" +
+ " --gdb: start gdbserv on the given port at crash/ANR\n" +
"\n" +
- " control screen compatibility: am screen-compat [on|off] [package]\n" +
+ "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
"\n" +
- " override display size: am display-size [reset|MxN]\n" +
+ "am display-size: override display size.\n" +
"\n" +
- " <INTENT> specifications include these flags:\n" +
- " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
- " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
- " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
- " [--esn <EXTRA_KEY> ...]\n" +
- " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
- " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
- " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
- " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
- " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
- " [-n <COMPONENT>] [-f <FLAGS>]\n" +
- " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
- " [--debug-log-resolution]\n" +
- " [--activity-brought-to-front] [--activity-clear-top]\n" +
- " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
- " [--activity-launched-from-history] [--activity-multiple-task]\n" +
- " [--activity-no-animation] [--activity-no-history]\n" +
- " [--activity-no-user-action] [--activity-previous-is-top]\n" +
- " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
- " [--activity-single-top]\n" +
- " [--receiver-registered-only] [--receiver-replace-pending]\n" +
- " [<URI>]\n"
+ "<INTENT> specifications include these flags and arguments:\n" +
+ " [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
+ " [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
+ " [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]\n" +
+ " [--esn <EXTRA_KEY> ...]\n" +
+ " [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]\n" +
+ " [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]\n" +
+ " [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]\n" +
+ " [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
+ " [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
+ " [-n <COMPONENT>] [-f <FLAGS>]\n" +
+ " [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+ " [--debug-log-resolution] [--exclude-stopped-packages]\n" +
+ " [--include-stopped-packages]\n" +
+ " [--activity-brought-to-front] [--activity-clear-top]\n" +
+ " [--activity-clear-when-task-reset] [--activity-exclude-from-recents]\n" +
+ " [--activity-launched-from-history] [--activity-multiple-task]\n" +
+ " [--activity-no-animation] [--activity-no-history]\n" +
+ " [--activity-no-user-action] [--activity-previous-is-top]\n" +
+ " [--activity-reorder-to-front] [--activity-reset-task-if-needed]\n" +
+ " [--activity-single-top] [--activity-clear-task]\n" +
+ " [--activity-task-on-home]\n" +
+ " [--receiver-registered-only] [--receiver-replace-pending]\n" +
+ " [<URI>]\n"
);
}
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 0acba8b..ccd668d 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -213,9 +213,10 @@
// create the native surface
sp<SurfaceControl> control = session()->createSurface(
0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
- session()->openTransaction();
+
+ SurfaceComposerClient::openGlobalTransaction();
control->setLayer(0x40000000);
- session()->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
sp<Surface> s = control->getSurface();
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index e81f799..4c4bf98 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -22,8 +22,6 @@
import android.os.ServiceManager;
import android.util.Log;
-import java.io.FileDescriptor;
-import java.io.IOException;
import java.util.ArrayList;
public final class Backup {
@@ -51,17 +49,19 @@
return;
}
+ int socketFd = Integer.parseInt(nextArg());
+
String arg = nextArg();
if (arg.equals("backup")) {
- doFullBackup();
+ doFullBackup(socketFd);
} else if (arg.equals("restore")) {
- doFullRestore();
+ doFullRestore(socketFd);
} else {
Log.e(TAG, "Invalid operation '" + arg + "'");
}
}
- private void doFullBackup() {
+ private void doFullBackup(int socketFd) {
ArrayList<String> packages = new ArrayList<String>();
boolean saveApks = false;
boolean saveShared = false;
@@ -100,24 +100,20 @@
}
try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.dup(FileDescriptor.out);
+ ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd);
String[] packArray = new String[packages.size()];
mBackupManager.fullBackup(fd, saveApks, saveShared, doEverything,
packages.toArray(packArray));
- } catch (IOException e) {
- Log.e(TAG, "Can't dup out");
} catch (RemoteException e) {
Log.e(TAG, "Unable to invoke backup manager for backup");
}
}
- private void doFullRestore() {
+ private void doFullRestore(int socketFd) {
// No arguments to restore
try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.dup(FileDescriptor.in);
+ ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd);
mBackupManager.fullRestore(fd);
- } catch (IOException e) {
- Log.e(TAG, "Can't dup System.in");
} catch (RemoteException e) {
Log.e(TAG, "Unable to invoke backup manager for restore");
}
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index d45ac192..26b9113 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -288,8 +288,9 @@
}
int get_size(const char *pkgname, const char *apkpath,
- const char *fwdlock_apkpath,
- int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize)
+ const char *fwdlock_apkpath, const char *asecpath,
+ int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
+ int64_t* _asecsize)
{
DIR *d;
int dfd;
@@ -300,6 +301,7 @@
int64_t codesize = 0;
int64_t datasize = 0;
int64_t cachesize = 0;
+ int64_t asecsize = 0;
/* count the source apk as code -- but only if it's not
* on the /system partition and its not on the sdcard.
@@ -324,6 +326,14 @@
}
}
+ /* compute asec size if it is given
+ */
+ if (asecpath != NULL && asecpath[0] != '!') {
+ if (stat(asecpath, &s) == 0) {
+ asecsize += stat_size(&s);
+ }
+ }
+
if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, 0)) {
goto done;
}
@@ -370,6 +380,7 @@
*_codesize = codesize;
*_datasize = datasize;
*_cachesize = cachesize;
+ *_asecsize = asecsize;
return 0;
}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index c062d36..feb6b92 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -77,16 +77,18 @@
int64_t codesize = 0;
int64_t datasize = 0;
int64_t cachesize = 0;
+ int64_t asecsize = 0;
int res = 0;
/* pkgdir, apkpath */
- res = get_size(arg[0], arg[1], arg[2], &codesize, &datasize, &cachesize);
+ res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize);
/*
* Each int64_t can take up 22 characters printed out. Make sure it
* doesn't go over REPLY_MAX in the future.
*/
- snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64, codesize, datasize, cachesize);
+ snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
+ codesize, datasize, cachesize, asecsize);
return res;
}
@@ -137,7 +139,7 @@
{ "freecache", 1, do_free_cache },
{ "rmcache", 1, do_rm_cache },
{ "protect", 2, do_protect },
- { "getsize", 3, do_get_size },
+ { "getsize", 4, do_get_size },
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 2, do_linklib },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index e5f6739..c5872b8 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -143,7 +143,8 @@
int rm_dex(const char *path);
int protect(char *pkgname, gid_t gid);
int get_size(const char *pkgname, const char *apkpath, const char *fwdlock_apkpath,
- int64_t *codesize, int64_t *datasize, int64_t *cachesize);
+ const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+ int64_t *asecsize);
int free_cache(int64_t free_size);
int dexopt(const char *apk_path, uid_t uid, int is_public);
int movefiles();
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index b48be6ef..1c1f37a 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -363,6 +363,7 @@
response = writeMasterKey(pw);
}
if (response == NO_ERROR) {
+ memcpy(mMasterKey, masterKeyBlob.getValue(), MASTER_KEY_SIZE_BYTES);
setupMasterKeys();
}
return response;
@@ -707,7 +708,7 @@
uid_t euid;
uint32_t perms;
} users[] = {
- {AID_SYSTEM, ~0, ~GET},
+ {AID_SYSTEM, ~0, ~0},
{AID_VPN, AID_SYSTEM, GET},
{AID_WIFI, AID_SYSTEM, GET},
{AID_ROOT, AID_SYSTEM, GET},
diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore
new file mode 100755
index 0000000..3be51b3
--- /dev/null
+++ b/cmds/keystore/test-keystore
@@ -0,0 +1,273 @@
+#!/bin/bash
+#
+# Copyright 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.
+
+set -e
+
+prefix=$0
+log_file=$prefix.log
+baseline_file=$prefix.baseline
+
+function cleanup_output() {
+ rm -f $log_file
+ rm -f $baseline_file
+}
+
+function log() {
+ echo "$@"
+ append $log_file \# "$@"
+ append $baseline_file \# "$@"
+}
+
+function expect() {
+ append $baseline_file "$@"
+}
+
+function append() {
+ declare -r file=$1
+ shift
+ echo "$@" >> $file
+}
+
+function run() {
+ # strip out carriage returns from adb
+ # strip out date/time from ls -l
+ "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
+}
+
+function keystore() {
+ declare -r user=$1
+ shift
+ run adb shell su $user keystore_cli "$@"
+}
+
+function list_keystore_directory() {
+ run adb shell ls -al /data/misc/keystore
+}
+
+function compare() {
+ log "comparing $baseline_file and $log_file"
+ diff $baseline_file $log_file || (log $tag FAILED && exit 1)
+}
+
+function test_basic() {
+
+ #
+ # reset
+ #
+ log "reset keystore as system user"
+ keystore system r
+ expect "1 No error"
+ list_keystore_directory
+
+ #
+ # basic tests as system/root
+ #
+ log "root does not have permission to run test"
+ keystore root t
+ expect "6 Permission denied"
+
+ log "but system user does"
+ keystore system t
+ expect "3 Uninitialized"
+ list_keystore_directory
+
+ log "password is now bar"
+ keystore system p bar
+ expect "1 No error"
+ list_keystore_directory
+ expect "-rw------- keystore keystore 84 .masterkey"
+
+ log "no error implies initialized and unlocked"
+ keystore system t
+ expect "1 No error"
+
+ log "saw with no argument"
+ keystore system s
+ expect "5 Protocol error"
+
+ log "saw nothing"
+ keystore system s ""
+ expect "1 No error"
+
+ log "add key baz"
+ keystore system i baz quux
+ expect "1 No error"
+
+ log "1000 is uid of system"
+ list_keystore_directory
+ expect "-rw------- keystore keystore 84 .masterkey"
+ expect "-rw------- keystore keystore 52 1000_baz"
+
+ log "saw baz"
+ keystore system s ""
+ expect "1 No error"
+ expect "baz"
+
+ log "get baz"
+ keystore system g baz
+ expect "1 No error"
+ expect "quux"
+
+ log "root can read system user keys (as can wifi or vpn users)"
+ keystore root g baz
+ expect "1 No error"
+ expect "quux"
+
+ #
+ # app user tests
+ #
+
+ # app_0 has uid 10000, as seen below
+ log "other uses cannot see the system keys"
+ keystore app_0 g baz
+ expect "7 Key not found"
+
+ log "app user cannot use reset, password, lock, unlock"
+ keystore app_0 r
+ expect "6 Permission denied"
+ keystore app_0 p
+ expect "6 Permission denied"
+ keystore app_0 l
+ expect "6 Permission denied"
+ keystore app_0 u
+ expect "6 Permission denied"
+
+ log "install app_0 key"
+ keystore app_0 i 0x deadbeef
+ expect 1 No error
+ list_keystore_directory
+ expect "-rw------- keystore keystore 84 .masterkey"
+ expect "-rw------- keystore keystore 52 10000_0x"
+ expect "-rw------- keystore keystore 52 1000_baz"
+
+ log "get with no argument"
+ keystore app_0 g
+ expect "5 Protocol error"
+
+ keystore app_0 g 0x
+ expect "1 No error"
+ expect "deadbeef"
+
+ keystore app_0 i fred barney
+ expect "1 No error"
+
+ keystore app_0 s ""
+ expect "1 No error"
+ expect "0x"
+ expect "fred"
+
+ log "note that saw returns the suffix of prefix matches"
+ keystore app_0 s fr # fred
+ expect "1 No error"
+ expect "ed" # fred
+
+ #
+ # lock tests
+ #
+ log "lock the store as system"
+ keystore system l
+ expect "1 No error"
+ keystore system t
+ expect "2 Locked"
+
+ log "saw works while locked"
+ keystore app_0 s ""
+ expect "1 No error"
+ expect "0x"
+ expect "fred"
+
+ log "...but cannot read keys..."
+ keystore app_0 g 0x
+ expect "2 Locked"
+
+ log "...but they can be deleted."
+ keystore app_0 e 0x
+ expect "1 No error"
+ keystore app_0 d 0x
+ expect "1 No error"
+ keystore app_0 e 0x
+ expect "7 Key not found"
+
+ #
+ # password
+ #
+ log "wrong password"
+ keystore system u foo
+ expect "13 Wrong password (4 tries left)"
+ log "right password"
+ keystore system u bar
+ expect "1 No error"
+
+ log "make the password foo"
+ keystore system p foo
+ expect "1 No error"
+
+ #
+ # final reset
+ #
+ log "reset wipes everything for all users"
+ keystore system r
+ expect "1 No error"
+ list_keystore_directory
+
+ keystore system t
+ expect "3 Uninitialized"
+
+}
+
+function test_4599735() {
+ # http://b/4599735
+ log "start regression test for b/4599735"
+ keystore system r
+ expect "1 No error"
+
+ keystore system p foo
+ expect "1 No error"
+
+ keystore system i baz quux
+ expect "1 No error"
+
+ keystore root g baz
+ expect "1 No error"
+ expect "quux"
+
+ keystore system l
+ expect "1 No error"
+
+ keystore system p foo
+ expect "1 No error"
+
+ log "after unlock, regression led to result of '8 Value corrupted'"
+ keystore root g baz
+ expect "1 No error"
+ expect "quux"
+
+ keystore system r
+ expect "1 No error"
+ log "end regression test for b/4599735"
+}
+
+function main() {
+ cleanup_output
+ log $tag START
+ test_basic
+ test_4599735
+ compare
+ log $tag PASSED
+ cleanup_output
+}
+
+main
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b0e4a86..c980715 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -120,12 +120,17 @@
return;
}
- if ("setInstallLocation".equals(op)) {
+ if ("disable-user".equals(op)) {
+ runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
+ return;
+ }
+
+ if ("set-install-location".equals(op)) {
runSetInstallLocation();
return;
}
- if ("getInstallLocation".equals(op)) {
+ if ("get-install-location".equals(op)) {
runGetInstallLocation();
return;
}
@@ -970,6 +975,8 @@
return "enabled";
case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
return "disabled";
+ case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
+ return "disabled-user";
}
return "unknown";
}
@@ -1087,8 +1094,7 @@
}
private static void showUsage() {
- System.err.println("usage: pm [list|path|install|uninstall]");
- System.err.println(" pm list packages [-f] [-d] [-e] [-s] [-e] [-u] [FILTER]");
+ System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-e] [-u] [FILTER]");
System.err.println(" pm list permission-groups");
System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
@@ -1100,66 +1106,66 @@
System.err.println(" pm clear PACKAGE");
System.err.println(" pm enable PACKAGE_OR_COMPONENT");
System.err.println(" pm disable PACKAGE_OR_COMPONENT");
- System.err.println(" pm setInstallLocation [0/auto] [1/internal] [2/external]");
+ System.err.println(" pm disable-user PACKAGE_OR_COMPONENT");
+ System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
+ System.err.println(" pm get-install-location");
System.err.println(" pm createUser USER_NAME");
System.err.println(" pm removeUser USER_ID");
System.err.println("");
- System.err.println("The list packages command prints all packages, optionally only");
- System.err.println("those whose package name contains the text in FILTER. Options:");
- System.err.println(" -f: see their associated file.");
- System.err.println(" -d: filter to only show disbled packages.");
- System.err.println(" -e: filter to only show enabled packages.");
- System.err.println(" -s: filter to only show system packages.");
- System.err.println(" -3: filter to only show third party packages.");
- System.err.println(" -u: also include uninstalled packages.");
+ System.err.println("pm list packages: prints all packages, optionally only");
+ System.err.println(" those whose package name contains the text in FILTER. Options:");
+ System.err.println(" -f: see their associated file.");
+ System.err.println(" -d: filter to only show disbled packages.");
+ System.err.println(" -e: filter to only show enabled packages.");
+ System.err.println(" -s: filter to only show system packages.");
+ System.err.println(" -3: filter to only show third party packages.");
+ System.err.println(" -u: also include uninstalled packages.");
System.err.println("");
- System.err.println("The list permission-groups command prints all known");
- System.err.println("permission groups.");
+ System.err.println("pm list permission-groups: prints all known permission groups.");
System.err.println("");
- System.err.println("The list permissions command prints all known");
- System.err.println("permissions, optionally only those in GROUP. Options:");
- System.err.println(" -g: organize by group.");
- System.err.println(" -f: print all information.");
- System.err.println(" -s: short summary.");
- System.err.println(" -d: only list dangerous permissions.");
- System.err.println(" -u: list only the permissions users will see.");
+ System.err.println("pm list permissions: prints all known permissions, optionally only");
+ System.err.println(" those in GROUP. Options:");
+ System.err.println(" -g: organize by group.");
+ System.err.println(" -f: print all information.");
+ System.err.println(" -s: short summary.");
+ System.err.println(" -d: only list dangerous permissions.");
+ System.err.println(" -u: list only the permissions users will see.");
System.err.println("");
- System.err.println("The list instrumentation command prints all instrumentations,");
- System.err.println("or only those that target a specified package. Options:");
- System.err.println(" -f: see their associated file.");
- System.err.println("(Use this command to list all test packages, or use <TARGET-PACKAGE> ");
- System.err.println(" to list the test packages for a particular application. The -f ");
- System.err.println(" option lists the .apk file for the test package.)");
+ System.err.println("pm list instrumentation: use to list all test packages; optionally");
+ System.err.println(" supply <TARGET-PACKAGE> to list the test packages for a particular");
+ System.err.println(" application. Options:");
+ System.err.println(" -f: list the .apk file for the test package.");
System.err.println("");
- System.err.println("The list features command prints all features of the system.");
+ System.err.println("pm list features: prints all features of the system.");
System.err.println("");
- System.err.println("The path command prints the path to the .apk of a package.");
+ System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
System.err.println("");
- System.err.println("The install command installs a package to the system. Options:");
- System.err.println(" -l: install the package with FORWARD_LOCK.");
- System.err.println(" -r: reinstall an exisiting app, keeping its data.");
- System.err.println(" -t: allow test .apks to be installed.");
- System.err.println(" -i: specify the installer package name.");
- System.err.println(" -s: install package on sdcard.");
- System.err.println(" -f: install package on internal flash.");
+ System.err.println("pm install: installs a package to the system. Options:");
+ System.err.println(" -l: install the package with FORWARD_LOCK.");
+ System.err.println(" -r: reinstall an exisiting app, keeping its data.");
+ System.err.println(" -t: allow test .apks to be installed.");
+ System.err.println(" -i: specify the installer package name.");
+ System.err.println(" -s: install package on sdcard.");
+ System.err.println(" -f: install package on internal flash.");
System.err.println("");
- System.err.println("The uninstall command removes a package from the system. Options:");
- System.err.println(" -k: keep the data and cache directories around.");
- System.err.println("after the package removal.");
+ System.err.println("pm uninstall: removes a package from the system. Options:");
+ System.err.println(" -k: keep the data and cache directories around after package removal.");
System.err.println("");
- System.err.println("The clear command deletes all data associated with a package.");
+ System.err.println("pm clear: deletes all data associated with a package.");
System.err.println("");
- System.err.println("The enable and disable commands change the enabled state of");
- System.err.println("a given package or component (written as \"package/class\").");
+ System.err.println("pm enable, disable, disable-user: these commands change the enabled state");
+ System.err.println(" of a given package or component (written as \"package/class\").");
System.err.println("");
- System.err.println("The getInstallLocation command gets the current install location");
- System.err.println(" 0 [auto]: Let system decide the best location");
- System.err.println(" 1 [internal]: Install on internal device storage");
- System.err.println(" 2 [external]: Install on external media");
+ System.err.println("pm get-install-location: returns the current install location.");
+ System.err.println(" 0 [auto]: Let system decide the best location");
+ System.err.println(" 1 [internal]: Install on internal device storage");
+ System.err.println(" 2 [external]: Install on external media");
System.err.println("");
- System.err.println("The setInstallLocation command changes the default install location");
- System.err.println(" 0 [auto]: Let system decide the best location");
- System.err.println(" 1 [internal]: Install on internal device storage");
- System.err.println(" 2 [external]: Install on external media");
+ System.err.println("pm set-install-location: changes the default install location.");
+ System.err.println(" NOTE: this is only intended for debugging; using this can cause");
+ System.err.println(" applications to break and other undersireable behavior.");
+ System.err.println(" 0 [auto]: Let system decide the best location");
+ System.err.println(" 1 [internal]: Install on internal device storage");
+ System.err.println(" 2 [external]: Install on external media");
}
}
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 289665f..6fa66cf 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -29,6 +29,7 @@
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/NativeWindowWrapper.h>
#include <media/stagefright/Utils.h>
#include <surfaceflinger/ISurfaceComposer.h>
@@ -39,10 +40,12 @@
using namespace android;
struct Controller : public AHandler {
- Controller(const char *uri, bool decodeAudio, const sp<Surface> &surface)
+ Controller(const char *uri, bool decodeAudio,
+ const sp<Surface> &surface, bool renderToSurface)
: mURI(uri),
mDecodeAudio(decodeAudio),
mSurface(surface),
+ mRenderToSurface(renderToSurface),
mCodec(new ACodec) {
CHECK(!mDecodeAudio || mSurface == NULL);
}
@@ -97,7 +100,8 @@
sp<AMessage> format = makeFormat(mSource->getFormat());
if (mSurface != NULL) {
- format->setObject("surface", mSurface);
+ format->setObject(
+ "native-window", new NativeWindowWrapper(mSurface));
}
mCodec->initiateSetup(format);
@@ -220,6 +224,7 @@
AString mURI;
bool mDecodeAudio;
sp<Surface> mSurface;
+ bool mRenderToSurface;
sp<ACodec> mCodec;
sp<MediaSource> mSource;
@@ -451,7 +456,7 @@
inBuffer->release();
inBuffer = NULL;
- // break; // Don't coalesce
+ break; // Don't coalesce
}
LOGV("coalesced %d input buffers", n);
@@ -479,6 +484,10 @@
sp<AMessage> reply;
CHECK(msg->findMessage("reply", &reply));
+ if (mRenderToSurface) {
+ reply->setInt32("render", 1);
+ }
+
reply->post();
}
@@ -491,7 +500,8 @@
fprintf(stderr, " -a(udio)\n");
fprintf(stderr,
- " -s(surface) Allocate output buffers on a surface.\n");
+ " -S(urface) Allocate output buffers on a surface.\n"
+ " -R(ender) Render surface-allocated buffers.\n");
}
int main(int argc, char **argv) {
@@ -499,18 +509,23 @@
bool decodeAudio = false;
bool useSurface = false;
+ bool renderToSurface = false;
int res;
- while ((res = getopt(argc, argv, "has")) >= 0) {
+ while ((res = getopt(argc, argv, "haSR")) >= 0) {
switch (res) {
case 'a':
decodeAudio = true;
break;
- case 's':
+ case 'S':
useSurface = true;
break;
+ case 'R':
+ renderToSurface = true;
+ break;
+
case '?':
case 'h':
default:
@@ -553,16 +568,18 @@
CHECK(control != NULL);
CHECK(control->isValid());
- CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+ SurfaceComposerClient::openGlobalTransaction();
CHECK_EQ(control->setLayer(30000), (status_t)OK);
CHECK_EQ(control->show(), (status_t)OK);
- CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
surface = control->getSurface();
CHECK(surface != NULL);
}
- sp<Controller> controller = new Controller(argv[0], decodeAudio, surface);
+ sp<Controller> controller =
+ new Controller(argv[0], decodeAudio, surface, renderToSurface);
+
looper->registerHandler(controller);
controller->startAsync();
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index ca77185..1a5b7f3 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -74,8 +74,6 @@
static sp<ANativeWindow> gSurface;
-#define USE_SURFACE_COMPOSER 0
-
static int64_t getNowUs() {
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -388,13 +386,15 @@
sp<MediaSource> mSource;
StreamType mStreamType;
+ bool mSawFirstIDRFrame;
DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
};
DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
: mSource(source),
- mStreamType(OTHER) {
+ mStreamType(OTHER),
+ mSawFirstIDRFrame(false) {
const char *mime;
CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
@@ -410,6 +410,8 @@
}
status_t DetectSyncSource::start(MetaData *params) {
+ mSawFirstIDRFrame = false;
+
return mSource->start(params);
}
@@ -439,16 +441,30 @@
status_t DetectSyncSource::read(
MediaBuffer **buffer, const ReadOptions *options) {
- status_t err = mSource->read(buffer, options);
+ for (;;) {
+ status_t err = mSource->read(buffer, options);
- if (err != OK) {
- return err;
- }
+ if (err != OK) {
+ return err;
+ }
- if (mStreamType == AVC && isIDRFrame(*buffer)) {
- (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
- } else {
- (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ if (mStreamType == AVC) {
+ bool isIDR = isIDRFrame(*buffer);
+ (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, isIDR);
+ if (isIDR) {
+ mSawFirstIDRFrame = true;
+ }
+ } else {
+ (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ }
+
+ if (mStreamType != AVC || mSawFirstIDRFrame) {
+ break;
+ }
+
+ // Ignore everything up to the first IDR frame.
+ (*buffer)->release();
+ *buffer = NULL;
}
return OK;
@@ -561,6 +577,7 @@
fprintf(stderr, " -x display a histogram of decoding times/fps "
"(video only)\n");
fprintf(stderr, " -S allocate buffers from a surface\n");
+ fprintf(stderr, " -T allocate buffers from a surface texture\n");
}
int main(int argc, char **argv) {
@@ -572,6 +589,7 @@
bool extractThumbnail = false;
bool seekTest = false;
bool useSurfaceAlloc = false;
+ bool useSurfaceTexAlloc = false;
gNumRepetitions = 1;
gMaxNumFrames = 0;
gReproduceBug = -1;
@@ -586,7 +604,7 @@
sp<LiveSession> liveSession;
int res;
- while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
+ while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxST")) >= 0) {
switch (res) {
case 'a':
{
@@ -677,6 +695,12 @@
break;
}
+ case 'T':
+ {
+ useSurfaceTexAlloc = true;
+ break;
+ }
+
case '?':
case 'h':
default:
@@ -825,34 +849,35 @@
sp<SurfaceComposerClient> composerClient;
sp<SurfaceControl> control;
- if (useSurfaceAlloc && !audioOnly) {
-#if USE_SURFACE_COMPOSER
- composerClient = new SurfaceComposerClient;
- CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+ if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+ if (useSurfaceAlloc) {
+ composerClient = new SurfaceComposerClient;
+ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
- control = composerClient->createSurface(
- getpid(),
- String8("A Surface"),
- 0,
- 1280,
- 800,
- PIXEL_FORMAT_RGB_565,
- 0);
+ control = composerClient->createSurface(
+ String8("A Surface"),
+ 0,
+ 1280,
+ 800,
+ PIXEL_FORMAT_RGB_565,
+ 0);
- CHECK(control != NULL);
- CHECK(control->isValid());
+ CHECK(control != NULL);
+ CHECK(control->isValid());
- CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
- CHECK_EQ(control->setLayer(30000), (status_t)OK);
- CHECK_EQ(control->show(), (status_t)OK);
- CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+ SurfaceComposerClient::openGlobalTransaction();
+ CHECK_EQ(control->setLayer(30000), (status_t)OK);
+ CHECK_EQ(control->show(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
- gSurface = control->getSurface();
- CHECK(gSurface != NULL);
-#else
- sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
- gSurface = new SurfaceTextureClient(texture);
-#endif
+ gSurface = control->getSurface();
+ CHECK(gSurface != NULL);
+ } else {
+ CHECK(useSurfaceTexAlloc);
+
+ sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
+ gSurface = new SurfaceTextureClient(texture);
+ }
}
DataSource::RegisterDefaultSniffers();
@@ -945,6 +970,17 @@
fprintf(stderr, "could not create extractor.\n");
return -1;
}
+
+ sp<MetaData> meta = extractor->getMetaData();
+
+ if (meta != NULL) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+ syncInfoPresent = false;
+ }
+ }
}
size_t numTracks = extractor->countTracks();
@@ -1032,12 +1068,12 @@
}
}
- if (useSurfaceAlloc && !audioOnly) {
+ if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
gSurface.clear();
-#if USE_SURFACE_COMPOSER
- composerClient->dispose();
-#endif
+ if (useSurfaceAlloc) {
+ composerClient->dispose();
+ }
}
client.disconnect();
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index f780afb..ee91c29 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -20,6 +20,11 @@
#include <media/mediaplayer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
@@ -31,7 +36,7 @@
using namespace android;
struct MyStreamSource : public BnStreamSource {
- // Caller retains ownership of fd.
+ // Object assumes ownership of fd.
MyStreamSource(int fd);
virtual void setListener(const sp<IStreamListener> &listener);
@@ -64,6 +69,8 @@
}
MyStreamSource::~MyStreamSource() {
+ close(mFd);
+ mFd = -1;
}
void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
@@ -99,6 +106,143 @@
mListener->queueBuffer(index, n);
}
}
+////////////////////////////////////////////////////////////////////////////////
+
+struct MyConvertingStreamSource : public BnStreamSource {
+ MyConvertingStreamSource(const char *filename);
+
+ virtual void setListener(const sp<IStreamListener> &listener);
+ virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
+
+ virtual void onBufferAvailable(size_t index);
+
+protected:
+ virtual ~MyConvertingStreamSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ sp<IStreamListener> mListener;
+ Vector<sp<IMemory> > mBuffers;
+
+ sp<MPEG2TSWriter> mWriter;
+
+ ssize_t mCurrentBufferIndex;
+ size_t mCurrentBufferOffset;
+
+ List<size_t> mBufferQueue;
+
+ static ssize_t WriteDataWrapper(void *me, const void *data, size_t size);
+ ssize_t writeData(const void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyConvertingStreamSource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+MyConvertingStreamSource::MyConvertingStreamSource(const char *filename)
+ : mCurrentBufferIndex(-1),
+ mCurrentBufferOffset(0) {
+ sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
+ CHECK(dataSource != NULL);
+
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+ CHECK(extractor != NULL);
+
+ mWriter = new MPEG2TSWriter(
+ this, &MyConvertingStreamSource::WriteDataWrapper);
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ const sp<MetaData> &meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (strncasecmp("video/", mime, 6) && strncasecmp("audio/", mime, 6)) {
+ continue;
+ }
+
+ CHECK_EQ(mWriter->addSource(extractor->getTrack(i)), (status_t)OK);
+ }
+
+ CHECK_EQ(mWriter->start(), (status_t)OK);
+}
+
+MyConvertingStreamSource::~MyConvertingStreamSource() {
+}
+
+void MyConvertingStreamSource::setListener(
+ const sp<IStreamListener> &listener) {
+ mListener = listener;
+}
+
+void MyConvertingStreamSource::setBuffers(
+ const Vector<sp<IMemory> > &buffers) {
+ mBuffers = buffers;
+}
+
+ssize_t MyConvertingStreamSource::WriteDataWrapper(
+ void *me, const void *data, size_t size) {
+ return static_cast<MyConvertingStreamSource *>(me)->writeData(data, size);
+}
+
+ssize_t MyConvertingStreamSource::writeData(const void *data, size_t size) {
+ size_t totalWritten = 0;
+
+ while (size > 0) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mCurrentBufferIndex < 0) {
+ while (mBufferQueue.empty()) {
+ mCondition.wait(mLock);
+ }
+
+ mCurrentBufferIndex = *mBufferQueue.begin();
+ mCurrentBufferOffset = 0;
+
+ mBufferQueue.erase(mBufferQueue.begin());
+ }
+
+ sp<IMemory> mem = mBuffers.itemAt(mCurrentBufferIndex);
+
+ size_t copy = size;
+ if (copy + mCurrentBufferOffset > mem->size()) {
+ copy = mem->size() - mCurrentBufferOffset;
+ }
+
+ memcpy((uint8_t *)mem->pointer() + mCurrentBufferOffset, data, copy);
+ mCurrentBufferOffset += copy;
+
+ if (mCurrentBufferOffset == mem->size()) {
+ mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+ mCurrentBufferIndex = -1;
+ }
+
+ data = (const uint8_t *)data + copy;
+ size -= copy;
+
+ totalWritten += copy;
+ }
+
+ return (ssize_t)totalWritten;
+}
+
+void MyConvertingStreamSource::onBufferAvailable(size_t index) {
+ Mutex::Autolock autoLock(mLock);
+
+ mBufferQueue.push_back(index);
+ mCondition.signal();
+
+ if (mWriter->reachedEOS()) {
+ if (mCurrentBufferIndex >= 0) {
+ mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+ mCurrentBufferIndex = -1;
+ }
+
+ mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
+ }
+}
////////////////////////////////////////////////////////////////////////////////
@@ -139,6 +283,8 @@
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
+ DataSource::RegisterDefaultSniffers();
+
if (argc != 2) {
fprintf(stderr, "Usage: %s filename\n", argv[0]);
return 1;
@@ -159,10 +305,10 @@
CHECK(control != NULL);
CHECK(control->isValid());
- CHECK_EQ(composerClient->openTransaction(), (status_t)OK);
+ SurfaceComposerClient::openGlobalTransaction();
CHECK_EQ(control->setLayer(30000), (status_t)OK);
CHECK_EQ(control->show(), (status_t)OK);
- CHECK_EQ(composerClient->closeTransaction(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
sp<Surface> surface = control->getSurface();
CHECK(surface != NULL);
@@ -173,17 +319,28 @@
CHECK(service.get() != NULL);
- int fd = open(argv[1], O_RDONLY);
-
- if (fd < 0) {
- fprintf(stderr, "Failed to open file '%s'.", argv[1]);
- return 1;
- }
-
sp<MyClient> client = new MyClient;
+ sp<IStreamSource> source;
+
+ size_t len = strlen(argv[1]);
+ if (len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) {
+ int fd = open(argv[1], O_RDONLY);
+
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open file '%s'.", argv[1]);
+ return 1;
+ }
+
+ source = new MyStreamSource(fd);
+ } else {
+ printf("Converting file to transport stream for streaming...\n");
+
+ source = new MyConvertingStreamSource(argv[1]);
+ }
+
sp<IMediaPlayer> player =
- service->create(getpid(), client, new MyStreamSource(fd), 0);
+ service->create(getpid(), client, source, 0);
if (player != NULL) {
player->setVideoSurface(surface);
@@ -196,9 +353,6 @@
fprintf(stderr, "failed to instantiate player.\n");
}
- close(fd);
- fd = -1;
-
composerClient->dispose();
return 0;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 164acbc..68c9926 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -31,82 +31,151 @@
* An accessibility service runs in the background and receives callbacks by the system
* when {@link AccessibilityEvent}s are fired. Such events denote some state transition
* in the user interface, for example, the focus has changed, a button has been clicked,
- * etc.
+ * etc. Such a service can optionally request the capability for querying the content
+ * of the active window. Development of an accessibility service requires extends this
+ * class and implements its abstract methods.
* <p>
- * An accessibility service extends this class and implements its abstract methods. Such
- * a service is declared as any other service in an AndroidManifest.xml but it must also
- * specify that it handles the "android.accessibilityservice.AccessibilityService"
- * {@link android.content.Intent}. Following is an example of such a declaration:
- * <p>
- * <code>
- * <service android:name=".MyAccessibilityService"><br>
- * <intent-filter><br>
- * <action android:name="android.accessibilityservice.AccessibilityService" /><br>
- * </intent-filter><br>
- * </service><br>
- * </code>
+ * <strong>Lifecycle</strong>
* </p>
* <p>
- * The lifecycle of an accessibility service is managed exclusively by the system. Starting
- * or stopping an accessibility service is triggered by an explicit user action through
+ * The lifecycle of an accessibility service is managed exclusively by the system and
+ * follows the established service life cycle. Additionally, starting or stopping an
+ * accessibility service is triggered exclusively by an explicit user action through
* enabling or disabling it in the device settings. After the system binds to a service it
* calls {@link AccessibilityService#onServiceConnected()}. This method can be
* overriden by clients that want to perform post binding setup.
* </p>
* <p>
+ * <strong>Declaration</strong>
+ * </p>
+ * <p>
+ * An accessibility is declared as any other service in an AndroidManifest.xml but it
+ * must also specify that it handles the "android.accessibilityservice.AccessibilityService"
+ * {@link android.content.Intent}. Failure to declare this intent will cause the system to
+ * ignore the accessibility service. Following is an example declaration:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ * <service android:name=".MyAccessibilityService">
+ * <intent-filter>
+ * <action android:name="android.accessibilityservice.AccessibilityService" />
+ * </intent-filter>
+ * . . .
+ * </service>
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Configuration</strong>
+ * </p>
+ * <p>
* An accessibility service can be configured to receive specific types of accessibility events,
* listen only to specific packages, get events from each type only once in a given time frame,
* retrieve window content, specify a settings activity, etc.
* </p>
+ * <p>
* There are two approaches for configuring an accessibility service:
+ * </p>
* <ul>
- * <li>
- * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
- * the service. A service declaration with a meta-data tag is presented below:
- * <p>
- * <code>
- * <service android:name=".MyAccessibilityService"><br>
- * <intent-filter><br>
- * <action android:name="android.accessibilityservice.AccessibilityService" /><br>
- * </intent-filter><br>
- * <meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /><br>
- * </service><br>
- * </code>
- * </p>
- * <p>
- * <strong>
- * This approach enables setting all accessibility service properties.
- * </strong>
- * </p>
- * <p>
- * For more details refer to {@link #SERVICE_META_DATA}.
- * </p>
- * </li>
- * <li>
- * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
- * that this method can be called any time to change the service configuration.<br>
- * <p>
- * <strong>
- * This approach enables setting only dynamically configurable accessibility
- * service properties:
- * {@link AccessibilityServiceInfo#eventTypes},
- * {@link AccessibilityServiceInfo#feedbackType},
- * {@link AccessibilityServiceInfo#flags},
- * {@link AccessibilityServiceInfo#notificationTimeout},
- * {@link AccessibilityServiceInfo#packageNames}
- * </strong>
- * </p>
- * <p>
- * For more details refer to {@link AccessibilityServiceInfo}.
- * </p>
- * </li>
+ * <li>
+ * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
+ * the service. A service declaration with a meta-data tag is presented below:
+ * <p>
+ * <code>
+ * <pre>
+ * <service android:name=".MyAccessibilityService">
+ * <intent-filter>
+ * <action android:name="android.accessibilityservice.AccessibilityService" />
+ * </intent-filter>
+ * <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" />
+ * </service>
+ * </pre>
+ * </code>
+ * </p>
+ * <p>
+ * <strong>Note:</strong>This approach enables setting all properties.
+ * </p>
+ * <p>
+ * For more details refer to {@link #SERVICE_META_DATA} and
+ * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>..
+ * </p>
+ * </li>
+ * <li>
+ * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
+ * that this method can be called any time to dynamically change the service configuration.
+ * <p>
+ * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
+ * {@link AccessibilityServiceInfo#eventTypes},
+ * {@link AccessibilityServiceInfo#feedbackType},
+ * {@link AccessibilityServiceInfo#flags},
+ * {@link AccessibilityServiceInfo#notificationTimeout},
+ * {@link AccessibilityServiceInfo#packageNames}
+ * </p>
+ * <p>
+ * For more details refer to {@link AccessibilityServiceInfo}.
+ * </p>
+ * </li>
* </ul>
* <p>
- * An accessibility service can be registered for events in specific packages to provide a
- * specific type of feedback and is notified with a certain timeout after the last event
- * of interest has been fired.
+ * <strong>Retrieving window content</strong>
+ * </p>
+ * <p>
+ * An service can specify in its declaration that it can retrieve the active window
+ * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
+ * declaring this capability requires that the service declares its configuration via
+ * an XML resource referenced by {@link #SERVICE_META_DATA}.
+ * </p>
+ * <p>
+ * For security purposes an accessibility service can retrieve only the content of the
+ * currently active window. The currently active window is defined as the window from
+ * which was fired the last event of the following types:
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
+ * {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
+ * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED},
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED},
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}.
+ * In other words, the active window is the one where the user interaction is taking place.
+ * </p>
+ * <p>
+ * The entry point for retrieving window content is through calling
+ * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
+ * event of the above types or a previous event from the same window
+ * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
+ * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
+ * window content which represented as a tree of such objects.
+ * </p>
+ * <p>
+ * <strong>Note</strong>An accessibility service may have requested to be notified for
+ * a subset of the event types, thus be unaware that the active window has changed. Therefore
+ * accessibility service that would like to retrieve window content should:
+ * <ul>
+ * <li>
+ * Register for all event types with no notification timeout and keep track for the active
+ * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
+ * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
+ * methods on the latter.
+ * </li>
+ * <li>
+ * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
+ * active window has changed and the service did not get the accessibility event yet. Note
+ * that it is possible to have a retrieval method failing event adopting the strategy
+ * specified in the previous bullet because the accessibility event dispatch is asynchronous
+ * and crosses process boundaries.
+ * </li>
+ * </ul>
+ * </p>
* <p>
* <b>Notification strategy</b>
+ * </p>
* <p>
* For each feedback type only one accessibility service is notified. Services are notified
* in the order of registration. Hence, if two services are registered for the same
@@ -117,9 +186,10 @@
* registration order. This enables "generic" accessibility services that work reasonably
* well with most applications to coexist with "polished" ones that are targeted for
* specific applications.
+ * </p>
* <p>
* <b>Event types</b>
- * <p>
+ * </p>
* {@link AccessibilityEvent#TYPE_VIEW_CLICKED}
* {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
* {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
@@ -127,9 +197,16 @@
* {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
* {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
* {@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
- * <p>
- * <b>Feedback types</b>
- * <p>
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
+ * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
+ * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
+ * {@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
+ * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
+ * <p>
+ * <b>Feedback types</b>
+ * <p>
* {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
* {@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
* {@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
@@ -140,10 +217,10 @@
* @see AccessibilityServiceInfo
* @see android.view.accessibility.AccessibilityManager
*
- * Note: The event notification timeout is useful to avoid propagating events to the client
- * too frequently since this is accomplished via an expensive interprocess call.
- * One can think of the timeout as a criteria to determine when event generation has
- * settled down.
+ * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
+ * events to the client too frequently since this is accomplished via an expensive
+ * interprocess call. One can think of the timeout as a criteria to determine when
+ * event generation has settled down.
*/
public abstract class AccessibilityService extends Service {
/**
@@ -154,57 +231,25 @@
/**
* Name under which an AccessibilityService component publishes information
- * about itself. This meta-data must reference an XML resource containing
- * an
+ * about itself. This meta-data must reference an XML resource containing an
* <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>
* tag. This is a a sample XML file configuring an accessibility service:
* <p>
* <code>
- * <?xml version="1.0" encoding="utf-8"?><br>
- * <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"<br>
- * android:accessibilityEventTypes="typeViewClicked|typeViewFocused"<br>
- * android:packageNames="foo.bar, foo.baz"<br>
- * android:accessibilityFeedbackType="feedbackSpoken"<br>
- * android:notificationTimeout="100"<br>
- * android:accessibilityFlags="flagDefault"<br>
- * android:settingsActivity="foo.bar.TestBackActivity"<br>
- * . . .<br>
+ * <pre>
+ * <accessibility-service
+ * android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
+ * android:packageNames="foo.bar, foo.baz"
+ * android:accessibilityFeedbackType="feedbackSpoken"
+ * android:notificationTimeout="100"
+ * android:accessibilityFlags="flagDefault"
+ * android:settingsActivity="foo.bar.TestBackActivity"
+ * android:canRetrieveWindowContent="true"
+ * . . .
* />
+ * </pre>
* </code>
* </p>
- * <p>
- * <strong>Note:</strong> A service can retrieve only the content of the active window.
- * An active window is the source of the most recent event of type
- * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START},
- * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END},
- * {@link AccessibilityEvent#TYPE_VIEW_CLICKED},
- * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED},
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
- * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
- * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED},
- * {@link AccessibilityEvent#TYPE_VIEW_SELECTED},
- * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED},
- * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}.
- * Therefore the service should:
- * <ul>
- * <li>
- * Register for all event types with no notification timeout and keep track
- * for the active window by calling
- * {@link AccessibilityEvent#getWindowId()} of the last received
- * event and compare this with the
- * {@link AccessibilityNodeInfo#getWindowId()} before calling
- * retrieval methods on the latter.
- * </li>
- * <li>
- * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail
- * since the active window has changed and the service did not get the
- * accessibility event. Note that it is possible to have a retrieval method
- * failing event adopting the strategy specified in the previous bullet
- * because the accessibility event dispatch is asynchronous and crosses
- * process boundaries.
- * </li>
- * <ul>
- * </p>
*/
public static final String SERVICE_META_DATA = "android.accessibilityservice";
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index b9878cd..ef4adca 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -37,13 +37,13 @@
import java.io.IOException;
/**
- * This class describes an {@link AccessibilityService}. The system
- * notifies an {@link AccessibilityService} for
- * {@link android.view.accessibility.AccessibilityEvent}s
+ * This class describes an {@link AccessibilityService}. The system notifies an
+ * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
* according to the information encapsulated in this class.
*
* @see AccessibilityService
* @see android.view.accessibility.AccessibilityEvent
+ * @see android.view.accessibility.AccessibilityManager
*/
public class AccessibilityServiceInfo implements Parcelable {
@@ -93,12 +93,19 @@
* @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
* @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
* @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
+ * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
*/
public int eventTypes;
/**
* The package names an {@link AccessibilityService} is interested in. Setting
- * to null is equivalent to all packages.
+ * to <code>null</code> is equivalent to all packages.
* <p>
* <strong>Can be dynamically set at runtime.</strong>
* </p>
@@ -125,10 +132,10 @@
* <strong>Can be dynamically set at runtime.</strong>.
* </p>
* <p>
- * Note: The event notification timeout is useful to avoid propagating events to the client
- * too frequently since this is accomplished via an expensive interprocess call.
- * One can think of the timeout as a criteria to determine when event generation has
- * settled down
+ * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
+ * events to the client too frequently since this is accomplished via an expensive
+ * interprocess call. One can think of the timeout as a criteria to determine when
+ * event generation has settled down.
*/
public long notificationTimeout;
@@ -159,7 +166,7 @@
private String mSettingsActivityName;
/**
- * Flag whether this accessibility service can retrieve screen content.
+ * Flag whether this accessibility service can retrieve window content.
*/
private boolean mCanRetrieveWindowContent;
@@ -296,12 +303,12 @@
}
/**
- * Whether this service can retrieve the currently focused window content.
+ * Whether this service can retrieve the current window's content.
* <p>
* <strong>Statically set from
* {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
* </p>
- * @return True screen content is retrieved.
+ * @return True window content can be retrieved.
*/
public boolean getCanRetrieveWindowContent() {
return mCanRetrieveWindowContent;
diff --git a/core/java/android/accessibilityservice/package.html b/core/java/android/accessibilityservice/package.html
new file mode 100644
index 0000000..0c640d1
--- /dev/null
+++ b/core/java/android/accessibilityservice/package.html
@@ -0,0 +1,22 @@
+<html>
+<body>
+<p>
+ The classes in this package are used for development of accessibility service that
+ provide alternative or augmented feedback to the user.
+</p>
+<p>
+ An {@link android.accessibilityservice.AccessibilityService} runs in the background and
+ receives callbacks by the system when {@link android.view.accessibility.AccessibilityEvent}s
+ are fired. Such events denote some state transition in the user interface, for example, the
+ focus has changed, a button has been clicked, etc. Such a service can optionally request the
+ capability for querying the content of the active window. Development of an accessibility
+ service requires extends this class and implements its abstract methods.
+</p>
+<p>
+ An {@link android.accessibilityservice.AccessibilityServiceInfo} describes an
+ {@link android.accessibilityservice.AccessibilityService}. The system notifies an
+ AccessibilityService for {@link android.view.accessibility.AccessibilityEvent}s
+ according to the information encapsulated in this class.
+</p>
+</body>
+</html>
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index c0c4c17..7183267 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -24,7 +24,6 @@
import android.content.Context;
import android.content.Intent;
import android.Manifest;
-import android.text.TextUtils;
import android.util.Log;
import java.util.Arrays;
@@ -136,17 +135,8 @@
if (result != null) {
response.onResult(result);
}
- } catch (NetworkErrorException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "addAccount", e);
- }
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
- } catch (UnsupportedOperationException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "addAccount", e);
- }
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "addAccount not supported");
+ } catch (Exception e) {
+ handleException(response, "addAccount", accountType, e);
}
}
@@ -167,17 +157,8 @@
if (result != null) {
response.onResult(result);
}
- } catch (NetworkErrorException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "confirmCredentials", e);
- }
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
- } catch (UnsupportedOperationException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "confirmCredentials", e);
- }
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "confirmCredentials not supported");
+ } catch (Exception e) {
+ handleException(response, "confirmCredentials", account.toString(), e);
}
}
@@ -197,21 +178,9 @@
Log.v(TAG, "getAuthTokenLabel: result "
+ AccountManager.sanitizeResult(result));
}
- if (result != null) {
- response.onResult(result);
- }
- } catch (IllegalArgumentException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "getAuthTokenLabel", e);
- }
- response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
- "unknown authTokenType");
- } catch (UnsupportedOperationException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "getAuthTokenLabel", e);
- }
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "getAuthTokenTypeLabel not supported");
+ response.onResult(result);
+ } catch (Exception e) {
+ handleException(response, "getAuthTokenLabel", authTokenType, e);
}
}
@@ -234,17 +203,9 @@
if (result != null) {
response.onResult(result);
}
- } catch (UnsupportedOperationException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "getAuthToken", e);
- }
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "getAuthToken not supported");
- } catch (NetworkErrorException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "getAuthToken", e);
- }
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+ } catch (Exception e) {
+ handleException(response, "getAuthToken",
+ account.toString() + "," + authTokenType, e);
}
}
@@ -267,17 +228,9 @@
if (result != null) {
response.onResult(result);
}
- } catch (NetworkErrorException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "updateCredentials", e);
- }
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
- } catch (UnsupportedOperationException e) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "updateCredentials", e);
- }
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "updateCredentials not supported");
+ } catch (Exception e) {
+ handleException(response, "updateCredentials",
+ account.toString() + "," + authTokenType, e);
}
}
@@ -290,9 +243,8 @@
if (result != null) {
response.onResult(result);
}
- } catch (UnsupportedOperationException e) {
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "editProperties not supported");
+ } catch (Exception e) {
+ handleException(response, "editProperties", accountType, e);
}
}
@@ -305,11 +257,8 @@
if (result != null) {
response.onResult(result);
}
- } catch (UnsupportedOperationException e) {
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "hasFeatures not supported");
- } catch (NetworkErrorException e) {
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+ } catch (Exception e) {
+ handleException(response, "hasFeatures", account.toString(), e);
}
}
@@ -322,15 +271,38 @@
if (result != null) {
response.onResult(result);
}
- } catch (UnsupportedOperationException e) {
- response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
- "getAccountRemovalAllowed not supported");
- } catch (NetworkErrorException e) {
- response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+ } catch (Exception e) {
+ handleException(response, "getAccountRemovalAllowed", account.toString(), e);
}
}
}
+ private void handleException(IAccountAuthenticatorResponse response, String method,
+ String data, Exception e) throws RemoteException {
+ if (e instanceof NetworkErrorException) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, method + "(" + data + ")", e);
+ }
+ response.onError(AccountManager.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+ } else if (e instanceof UnsupportedOperationException) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, method + "(" + data + ")", e);
+ }
+ response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
+ method + " not supported");
+ } else if (e instanceof IllegalArgumentException) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, method + "(" + data + ")", e);
+ }
+ response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+ method + " not supported");
+ } else {
+ Log.w(TAG, method + "(" + data + ")", e);
+ response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
+ method + " failed");
+ }
+ }
+
private void checkBinderPermission() {
final int uid = Binder.getCallingUid();
final String perm = Manifest.permission.ACCOUNT_MANAGER;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 85f40c9..fdf4a3a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -251,12 +251,13 @@
IBinder b = data.readStrongBinder();
IApplicationThread app =
b != null ? ApplicationThreadNative.asInterface(b) : null;
+ String packageName = data.readString();
b = data.readStrongBinder();
IIntentReceiver rec
= b != null ? IIntentReceiver.Stub.asInterface(b) : null;
IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
String perm = data.readString();
- Intent intent = registerReceiver(app, rec, filter, perm);
+ Intent intent = registerReceiver(app, packageName, rec, filter, perm);
reply.writeNoException();
if (intent != null) {
reply.writeInt(1);
@@ -1503,6 +1504,16 @@
return true;
}
+ case IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IIntentSender r = IIntentSender.Stub.asInterface(
+ data.readStrongBinder());
+ boolean res = isIntentSenderTargetedToPackage(r);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -1702,7 +1713,7 @@
reply.recycle();
return res;
}
- public Intent registerReceiver(IApplicationThread caller,
+ public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm) throws RemoteException
{
@@ -1710,6 +1721,7 @@
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
+ data.writeString(packageName);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
@@ -3385,5 +3397,18 @@
reply.recycle();
}
+ public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(sender.asBinder());
+ mRemote.transact(IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 7a465c1..491fcfe 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -890,7 +890,10 @@
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
P.apply(dialog.mAlert);
- dialog.setCanceledOnTouchOutside(P.mCancelable);
+ dialog.setCancelable(P.mCancelable);
+ if (P.mCancelable) {
+ dialog.setCanceledOnTouchOutside(true);
+ }
dialog.setOnCancelListener(P.mOnCancelListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 94a4afa..8749d3e 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -61,7 +61,6 @@
import android.net.wifi.WifiManager;
import android.nfc.NfcManager;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.Environment;
@@ -81,7 +80,6 @@
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.view.ContextThemeWrapper;
-import android.view.Display;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethodManager;
@@ -142,6 +140,7 @@
new HashMap<String, SharedPreferencesImpl>();
/*package*/ LoadedApk mPackageInfo;
+ private String mBasePackageName;
private Resources mResources;
/*package*/ ActivityThread mMainThread;
private Context mOuterContext;
@@ -1030,7 +1029,7 @@
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
- mMainThread.getApplicationThread(),
+ mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission);
} catch (RemoteException e) {
return null;
@@ -1397,7 +1396,7 @@
if (pi != null) {
ContextImpl c = new ContextImpl();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
- c.init(pi, null, mMainThread, mResources);
+ c.init(pi, null, mMainThread, mResources, mBasePackageName);
if (c.mResources != null) {
return c;
}
@@ -1450,6 +1449,7 @@
*/
public ContextImpl(ContextImpl context) {
mPackageInfo = context.mPackageInfo;
+ mBasePackageName = context.mBasePackageName;
mResources = context.mResources;
mMainThread = context.mMainThread;
mContentResolver = context.mContentResolver;
@@ -1458,13 +1458,14 @@
final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread) {
- init(packageInfo, activityToken, mainThread, null);
+ init(packageInfo, activityToken, mainThread, null, null);
}
final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread,
- Resources container) {
+ Resources container, String basePackageName) {
mPackageInfo = packageInfo;
+ mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
mResources = mPackageInfo.getResources(mainThread);
if (mResources != null && container != null
@@ -1485,6 +1486,7 @@
final void init(Resources resources, ActivityThread mainThread) {
mPackageInfo = null;
+ mBasePackageName = null;
mResources = resources;
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 28559cc..ad8d41f 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -226,6 +226,14 @@
public final static int ERROR_FILE_ALREADY_EXISTS = 1009;
/**
+ * Value of {@link #COLUMN_REASON} when the download has failed because of
+ * {@link NetworkPolicyManager} controls on the requesting application.
+ *
+ * @hide
+ */
+ public final static int ERROR_BLOCKED = 1010;
+
+ /**
* Value of {@link #COLUMN_REASON} when the download is paused because some network error
* occurred and the download manager is waiting before retrying the request.
*/
@@ -249,14 +257,6 @@
public final static int PAUSED_UNKNOWN = 4;
/**
- * Value of {@link #COLUMN_REASON} when the download has been paused because
- * of {@link NetworkPolicyManager} controls on the requesting application.
- *
- * @hide
- */
- public final static int PAUSED_BY_POLICY = 5;
-
- /**
* Broadcast intent action sent by the download manager when a download completes.
*/
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
@@ -804,7 +804,6 @@
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY));
parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK));
parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI));
- parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_POLICY));
}
if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) {
parts.add(statusClause("=", Downloads.Impl.STATUS_SUCCESS));
@@ -1275,9 +1274,6 @@
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
return PAUSED_QUEUED_FOR_WIFI;
- case Downloads.Impl.STATUS_PAUSED_BY_POLICY:
- return PAUSED_BY_POLICY;
-
default:
return PAUSED_UNKNOWN;
}
@@ -1316,6 +1312,9 @@
case Downloads.Impl.STATUS_FILE_ALREADY_EXISTS_ERROR:
return ERROR_FILE_ALREADY_EXISTS;
+ case Downloads.Impl.STATUS_BLOCKED:
+ return ERROR_BLOCKED;
+
default:
return ERROR_UNKNOWN;
}
@@ -1333,7 +1332,6 @@
case Downloads.Impl.STATUS_WAITING_TO_RETRY:
case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
- case Downloads.Impl.STATUS_PAUSED_BY_POLICY:
return STATUS_PAUSED;
case Downloads.Impl.STATUS_SUCCESS:
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e2588cf..9e20764 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -103,7 +103,7 @@
throws RemoteException;
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
public boolean willActivityBeVisible(IBinder token) throws RemoteException;
- public Intent registerReceiver(IApplicationThread caller,
+ public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter,
String requiredPermission) throws RemoteException;
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException;
@@ -361,6 +361,8 @@
public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
+ public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -587,4 +589,5 @@
int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
+ int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
}
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index cb03d2c..688cdfd 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -19,6 +19,7 @@
import android.app.SearchableInfo;
import android.app.ISearchManagerCallback;
import android.content.ComponentName;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -26,6 +27,7 @@
interface ISearchManager {
SearchableInfo getSearchableInfo(in ComponentName launchActivity);
List<SearchableInfo> getSearchablesInGlobalSearch();
+ List<ResolveInfo> getGlobalSearchActivities();
ComponentName getGlobalSearchActivity();
ComponentName getWebSearchActivity();
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c9351af..170d2b5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -929,15 +929,15 @@
if (mContentInfo != null) {
contentView.setTextViewText(R.id.info, mContentInfo);
} else if (mNumber > 0) {
- if (mNumber > 999) {
- contentView.setTextViewText(R.id.info, "999+");
+ final int tooBig = mContext.getResources().getInteger(
+ R.integer.status_bar_notification_info_maxnum);
+ if (mNumber > tooBig) {
+ contentView.setTextViewText(R.id.info, mContext.getResources().getString(
+ R.string.status_bar_notification_info_overflow));
} else {
NumberFormat f = NumberFormat.getIntegerInstance();
contentView.setTextViewText(R.id.info, f.format(mNumber));
}
- contentView.setFloat(R.id.info, "setTextSize",
- mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_content_number_size));
} else {
contentView.setViewVisibility(R.id.info, View.GONE);
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 5b43b65..b4827cb 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -365,7 +365,7 @@
* is no longer allowing more intents to be sent through it.
*/
public void send() throws CanceledException {
- send(null, 0, null, null, null);
+ send(null, 0, null, null, null, null);
}
/**
@@ -379,7 +379,7 @@
* is no longer allowing more intents to be sent through it.
*/
public void send(int code) throws CanceledException {
- send(null, code, null, null, null);
+ send(null, code, null, null, null, null);
}
/**
@@ -399,7 +399,7 @@
*/
public void send(Context context, int code, Intent intent)
throws CanceledException {
- send(context, code, intent, null, null);
+ send(context, code, intent, null, null, null);
}
/**
@@ -420,7 +420,7 @@
*/
public void send(int code, OnFinished onFinished, Handler handler)
throws CanceledException {
- send(null, code, null, onFinished, handler);
+ send(null, code, null, onFinished, handler, null);
}
/**
@@ -449,20 +449,64 @@
* @see #send(int)
* @see #send(Context, int, Intent)
* @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+ * @see #send(Context, int, Intent, OnFinished, Handler, String)
*
* @throws CanceledException Throws CanceledException if the PendingIntent
* is no longer allowing more intents to be sent through it.
*/
public void send(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler) throws CanceledException {
+ send(context, code, intent, onFinished, handler, null);
+ }
+
+ /**
+ * Perform the operation associated with this PendingIntent, allowing the
+ * caller to specify information about the Intent to use and be notified
+ * when the send has completed.
+ *
+ * <p>For the intent parameter, a PendingIntent
+ * often has restrictions on which fields can be supplied here, based on
+ * how the PendingIntent was retrieved in {@link #getActivity},
+ * {@link #getBroadcast}, or {@link #getService}.
+ *
+ * @param context The Context of the caller. This may be null if
+ * <var>intent</var> is also null.
+ * @param code Result code to supply back to the PendingIntent's target.
+ * @param intent Additional Intent data. See {@link Intent#fillIn
+ * Intent.fillIn()} for information on how this is applied to the
+ * original Intent. Use null to not modify the original Intent.
+ * @param onFinished The object to call back on when the send has
+ * completed, or null for no callback.
+ * @param handler Handler identifying the thread on which the callback
+ * should happen. If null, the callback will happen from the thread
+ * pool of the process.
+ * @param requiredPermission Name of permission that a recipient of the PendingIntent
+ * is required to hold. This is only valid for broadcast intents, and
+ * corresponds to the permission argument in
+ * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+ * If null, no permission is required.
+ *
+ * @see #send()
+ * @see #send(int)
+ * @see #send(Context, int, Intent)
+ * @see #send(int, android.app.PendingIntent.OnFinished, Handler)
+ * @see #send(Context, int, Intent, OnFinished, Handler)
+ *
+ * @throws CanceledException Throws CanceledException if the PendingIntent
+ * is no longer allowing more intents to be sent through it.
+ */
+ public void send(Context context, int code, Intent intent,
+ OnFinished onFinished, Handler handler, String requiredPermission)
+ throws CanceledException {
try {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
: null;
int res = mTarget.send(code, intent, resolvedType,
onFinished != null
- ? new FinishedDispatcher(this, onFinished, handler)
- : null);
+ ? new FinishedDispatcher(this, onFinished, handler)
+ : null,
+ requiredPermission);
if (res < 0) {
throw new CanceledException();
}
@@ -491,6 +535,20 @@
}
/**
+ * @hide
+ * Check to verify that this PendingIntent targets a specific package.
+ */
+ public boolean isTargetedToPackage() {
+ try {
+ return ActivityManagerNative.getDefault()
+ .isIntentSenderTargetedToPackage(mTarget);
+ } catch (RemoteException e) {
+ // Should never happen.
+ return false;
+ }
+ }
+
+ /**
* Comparison operator on two PendingIntent objects, such that true
* is returned then they both represent the same operation from the
* same package. This allows you to use {@link #getActivity},
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9cb57be..41eea2e 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -80,6 +80,7 @@
private View mSearchPlate;
private SearchView mSearchView;
private Drawable mWorkingSpinner;
+ private View mCloseSearch;
// interaction with searchable application
private SearchableInfo mSearchable;
@@ -167,11 +168,18 @@
SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar);
searchBar.setSearchDialog(this);
mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
- mSearchView.setSubmitButtonEnabled(true);
mSearchView.setOnCloseListener(mOnCloseListener);
mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener);
+ mCloseSearch = findViewById(com.android.internal.R.id.closeButton);
+ mCloseSearch.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ }
+ });
+
// TODO: Move the badge logic to SearchView or move the badge to search_bar.xml
mBadgeLabel = (TextView) mSearchView.findViewById(com.android.internal.R.id.search_badge);
mSearchAutoComplete = (AutoCompleteTextView)
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 8f646c5..7274362 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
@@ -383,6 +384,17 @@
= "android.search.action.SEARCHABLES_CHANGED";
/**
+ * Intent action to be broadcast to inform that the global search provider
+ * has changed. Normal components will have no need to handle this intent since
+ * they should be using API methods from this class to access the global search
+ * activity
+ *
+ * @hide
+ */
+ public final static String INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED
+ = "android.search.action.GLOBAL_SEARCH_ACTIVITY_CHANGED";
+
+ /**
* Intent action broadcasted to inform that the search settings have changed in some way.
* Either searchables have been enabled or disabled, or a different web search provider
* has been chosen.
@@ -535,6 +547,21 @@
}
/**
+ * Returns a list of installed apps that handle the global search
+ * intent.
+ *
+ * @hide
+ */
+ public List<ResolveInfo> getGlobalSearchActivities() {
+ try {
+ return mService.getGlobalSearchActivities();
+ } catch (RemoteException ex) {
+ Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
+ return null;
+ }
+ }
+
+ /**
* Gets the name of the global search activity.
*
* @hide
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a8c31f9..b993bd8 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1115,6 +1115,9 @@
} else if (profile == BluetoothProfile.PAN) {
BluetoothPan pan = new BluetoothPan(context, listener);
return true;
+ } else if (profile == BluetoothProfile.HEALTH) {
+ BluetoothHealth health = new BluetoothHealth(context, listener);
+ return true;
} else {
return false;
}
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
new file mode 100644
index 0000000..52efc07
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -0,0 +1,444 @@
+/*
+ * 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 android.bluetooth;
+
+import android.annotation.SdkConstant;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Public API for Bluetooth Health Profile.
+ *
+ * <p>BluetoothHealth is a proxy object for controlling the Bluetooth
+ * Service via IPC.
+ *
+ * <p> Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothHealth proxy object. Use
+ * {@link BluetoothAdapter#closeProfileProxy} to close the service connection.
+ * @hide
+ */
+public final class BluetoothHealth implements BluetoothProfile {
+ private static final String TAG = "BluetoothHealth";
+ private static final boolean DBG = false;
+
+ /**
+ * Health Profile Source Role - the health device.
+ */
+ public static final int SOURCE_ROLE = 1 << 0;
+
+ /**
+ * Health Profile Sink Role the device talking to the health device.
+ */
+ public static final int SINK_ROLE = 1 << 1;
+
+ /**
+ * Health Profile - Channel Type used - Reliable
+ */
+ public static final int CHANNEL_TYPE_RELIABLE = 10;
+
+ /**
+ * Health Profile - Channel Type used - Streaming
+ */
+ public static final int CHANNEL_TYPE_STREAMING = 11;
+
+ /**
+ * @hide
+ */
+ public static final int CHANNEL_TYPE_ANY = 12;
+
+ private final ArrayList<BluetoothHealthAppConfiguration> mAppConfigs =
+ new ArrayList<BluetoothHealthAppConfiguration>();
+
+ /**
+ * Register an application configuration that acts as a Health SINK.
+ * This is the configuration that will be used to communicate with health devices
+ * which will act as the {@link #SOURCE_ROLE}. This is an asynchronous call and so
+ * the callback is used to notify success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param name The friendly name associated with the application or configuration.
+ * @param dataType The dataType of the Source role of Health Profile to which
+ * the sink wants to connect to.
+ * @param callback A callback to indicate success or failure of the registration and
+ * all operations done on this application configuration.
+ * @return If true, callback will be called.
+ */
+ public boolean registerSinkAppConfiguration(String name, int dataType,
+ IBluetoothHealthCallback callback) {
+ if (!isEnabled() || name == null) return false;
+
+ if (DBG) log("registerSinkApplication(" + name + ":" + dataType + ")");
+ return registerAppConfiguration(name, dataType, SINK_ROLE,
+ CHANNEL_TYPE_ANY, callback);
+ }
+
+ /**
+ * Register an application configuration that acts as a Health SINK or in a Health
+ * SOURCE role.This is an asynchronous call and so
+ * the callback is used to notify success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param name The friendly name associated with the application or configuration.
+ * @param dataType The dataType of the Source role of Health Profile.
+ * @param channelType The channel type. Will be one of
+ * {@link #CHANNEL_TYPE_RELIABLE} or
+ * {@link #CHANNEL_TYPE_STREAMING}
+ * @param callback - A callback to indicate success or failure.
+ * @return If true, callback will be called.
+ * @hide
+ */
+ public boolean registerAppConfiguration(String name, int dataType, int role,
+ int channelType, IBluetoothHealthCallback callback) {
+ boolean result = false;
+ if (!isEnabled() || !checkAppParam(name, role, channelType, callback)) return result;
+
+ if (DBG) log("registerApplication(" + name + ":" + dataType + ")");
+ BluetoothHealthAppConfiguration config =
+ new BluetoothHealthAppConfiguration(name, dataType, role, channelType,
+ callback);
+
+ if (mService != null) {
+ try {
+ result = mService.registerAppConfiguration(config);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+
+ if (result) mAppConfigs.add(config);
+ return result;
+ }
+
+ /**
+ * Unregister an application configuration that has been registered using
+ * {@link #registerSinkAppConfiguration}
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param config The health app configuration
+ * @return Success or failure.
+ * @hide
+ */
+ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+ boolean result = false;
+ if (mService != null && isEnabled() && isValidAppConfig(config)) {
+ try {
+ result = mService.unregisterAppConfiguration(config);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ if (result) mAppConfigs.remove(config);
+ return result;
+ }
+
+ /**
+ * Connect to a health device which has the {@link #SOURCE_ROLE}.
+ * This is an asynchrnous call. If this function returns true, the callback
+ * associated with the application configuration will be called.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device The remote Bluetooth device.
+ * @param config The application configuration which has been registed using
+ * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @return If true, the callback associated with the application config will be called.
+ */
+ public boolean connectChannelToSource(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ if (mService != null && isEnabled() && isValidDevice(device) &&
+ isValidAppConfig(config)) {
+ try {
+ return mService.connectChannelToSource(device, config);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Connect to a health device which has the {@link #SINK_ROLE}.
+ * This is an asynchronous call. If this function returns true, the callback
+ * associated with the application configuration will be called.
+ *
+ *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device The remote Bluetooth device.
+ * @param config The application configuration which has been registed using
+ * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @return If true, the callback associated with the application config will be called.
+ * @hide
+ */
+ public boolean connectChannelToSink(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int channelType) {
+ if (mService != null && isEnabled() && isValidDevice(device) &&
+ isValidAppConfig(config)) {
+ try {
+ return mService.connectChannelToSink(device, config, channelType);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Disconnect a connected health channel.
+ * This is an asynchronous call. If this function returns true, the callback
+ * associated with the application configuration will be called.
+ *
+ *<p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device The remote Bluetooth device.
+ * @param config The application configuration which has been registed using
+ * {@link #registerSinkAppConfiguration(String, int, IBluetoothHealthCallback) }
+ * @param fd The file descriptor that was associated with the channel.
+ * @return If true, the callback associated with the application config will be called.
+ * @hide
+ */
+ public boolean disconnectChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ if (mService != null && isEnabled() && isValidDevice(device) &&
+ isValidAppConfig(config)) {
+ try {
+ return mService.disconnectChannel(device, config, fd);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Get the file descriptor of the main channel associated with the remote device
+ * and application configuration.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device The remote Bluetooth health device
+ * @param config The application configuration
+ * @return null on failure, ParcelFileDescriptor on success.
+ */
+
+ public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ if (mService != null && isEnabled() && isValidDevice(device) &&
+ isValidAppConfig(config)) {
+ try {
+ return mService.getMainChannelFd(device, config);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return null;
+ }
+
+ /**
+ * Get the current connection state of the profile.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * This is not specific to any application configuration but represents the connection
+ * state of the local Bluetooth adapter with the remote device. This can be used
+ * by applications like status bar which would just like to know the state of the
+ * local adapter.
+ *
+ * @param device Remote bluetooth device.
+ * @return State of the profile connection. One of
+ * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.getHealthDeviceConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return STATE_DISCONNECTED;
+ }
+
+ /**
+ * Get connected devices for this specific profile.
+ *
+ * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * This is not specific to any application configuration but represents the connection
+ * state of the local Bluetooth adapter for this profile. This can be used
+ * by applications like status bar which would just like to know the state of the
+ * local adapter.
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedHealthDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * Get a list of devices that match any of the given connection
+ * states.
+ *
+ * <p> If none of the devices match any of the given states,
+ * an empty list will be returned.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ * This is not specific to any application configuration but represents the connection
+ * state of the local Bluetooth adapter for this profile. This can be used
+ * by applications like status bar which would just like to know the state of the
+ * local adapter.
+ *
+ * @param states Array of states. States can be one of
+ * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getHealthDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /** Health Channel Connection State - Disconnected */
+ public static final int STATE_CHANNEL_DISCONNECTED = 0;
+ /** Health Channel Connection State - Connecting */
+ public static final int STATE_CHANNEL_CONNECTING = 1;
+ /** Health Channel Connection State - Connected */
+ public static final int STATE_CHANNEL_CONNECTED = 2;
+ /** Health Channel Connection State - Disconnecting */
+ public static final int STATE_CHANNEL_DISCONNECTING = 3;
+
+ /** Health App Configuration registration success */
+ public static final int APPLICATION_REGISTRATION_SUCCESS = 0;
+ /** Health App Configuration registration failure */
+ public static final int APPLICATION_REGISTRATION_FAILURE = 1;
+ /** Health App Configuration un-registration success */
+ public static final int APPLICATION_UNREGISTRATION_SUCCESS = 2;
+ /** Health App Configuration un-registration failure */
+ public static final int APPLICATION_UNREGISTRATION_FAILURE = 3;
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private IBluetooth mService;
+ BluetoothAdapter mAdapter;
+
+ /**
+ * Create a BluetoothHealth proxy object.
+ */
+ /*package*/ BluetoothHealth(Context mContext, ServiceListener l) {
+ IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (b != null) {
+ mService = IBluetooth.Stub.asInterface(b);
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.HEALTH, this);
+ }
+ } else {
+ Log.w(TAG, "Bluetooth Service not available!");
+
+ // Instead of throwing an exception which prevents people from going
+ // into Wireless settings in the emulator. Let it crash later when it is actually used.
+ mService = null;
+ }
+ }
+
+ private boolean isEnabled() {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+
+ if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ log("Bluetooth is Not enabled");
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private boolean isValidAppConfig(BluetoothHealthAppConfiguration config) {
+ if (!mAppConfigs.isEmpty() && mAppConfigs.contains(config)) return true;
+ log("Not a valid config: " + config);
+ return false;
+ }
+
+ private boolean checkAppParam(String name, int role, int channelType,
+ IBluetoothHealthCallback callback) {
+ if (name == null || (role != SOURCE_ROLE && role != SINK_ROLE) ||
+ (channelType != CHANNEL_TYPE_RELIABLE &&
+ channelType != CHANNEL_TYPE_STREAMING &&
+ channelType != CHANNEL_TYPE_ANY) || callback == null) {
+ return false;
+ }
+ if (role == SOURCE_ROLE && channelType == CHANNEL_TYPE_ANY) return false;
+ return true;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl
new file mode 100644
index 0000000..bc9e54f
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 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 android.bluetooth;
+
+parcelable BluetoothHealthAppConfiguration;
diff --git a/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
new file mode 100644
index 0000000..b87aea5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHealthAppConfiguration.java
@@ -0,0 +1,180 @@
+/*
+ * 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 android.bluetooth;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The Bluetooth Health Application Configuration that is used in conjunction with
+ * the {@link BluetoothHealth} class. This class represents an application configuration
+ * that the Bluetooth Health third party application will register to communicate with the
+ * remote Bluetooth health device.
+ *
+ * @hide
+ */
+public final class BluetoothHealthAppConfiguration implements Parcelable {
+ private final String mName;
+ private final int mDataType;
+ private final int mRole;
+ private final int mChannelType;
+ private final IBluetoothHealthCallback mCallback;
+
+ /**
+ * Constructor to register the SINK role
+ *
+ * @param name Friendly name associated with the application configuration
+ * @param dataType Data Type of the remote Bluetooth Health device
+ * @param callback Callback associated with the application configuration.
+ */
+ BluetoothHealthAppConfiguration(String name, int dataType, IBluetoothHealthCallback callback) {
+ mName = name;
+ mDataType = dataType;
+ mRole = BluetoothHealth.SINK_ROLE;
+ mChannelType = BluetoothHealth.CHANNEL_TYPE_ANY;
+ mCallback = callback;
+ }
+
+ /**
+ * Constructor to register the application configuration.
+ *
+ * @param name Friendly name associated with the application configuration
+ * @param dataType Data Type of the remote Bluetooth Health device
+ * @param role {@link BluetoothHealth.SOURCE_ROLE} or
+ * {@link BluetoothHealth.SINK_ROLE}
+ * @param callback Callback associated with the application configuration.
+ */
+ BluetoothHealthAppConfiguration(String name, int dataType, int role, int channelType,
+ IBluetoothHealthCallback callback) {
+ mName = name;
+ mDataType = dataType;
+ mRole = role;
+ mChannelType = channelType;
+ mCallback = callback;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothHealthAppConfiguration) {
+ BluetoothHealthAppConfiguration config = (BluetoothHealthAppConfiguration) o;
+ // config.getName() can never be NULL
+ return mName.equals(config.getName()) &&
+ mDataType == config.getDataType() &&
+ mRole == config.getRole() &&
+ mChannelType == config.getChannelType() &&
+ mCallback.equals(config.getCallback());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (mName != null ? mName.hashCode() : 0);
+ result = 31 * result + mDataType;
+ result = 31 * result + mRole;
+ result = 31 * result + mChannelType;
+ result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "BluetoothHealthAppConfiguration [mName = " + mName +
+ ",mDataType = " + mDataType + ", mRole = " + mRole + ",mChannelType = " +
+ mChannelType + ",callback=" + mCallback +"]";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Return the data type associated with this application configuration.
+ *
+ * @return dataType
+ */
+ public int getDataType() {
+ return mDataType;
+ }
+
+ /**
+ * Return the name of the application configuration.
+ *
+ * @return String name
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Return the role associated with this application configuration.
+ *
+ * @return One of {@link BluetoothHealth#SOURCE_ROLE} or
+ * {@link BluetoothHealth#SINK_ROLE}
+ */
+ public int getRole() {
+ return mRole;
+ }
+
+ /**
+ * Return the channel type associated with this application configuration.
+ *
+ * @return One of {@link BluetoothHealth#CHANNEL_TYPE_RELIABLE} or
+ * {@link BluetoothHealth#CHANNEL_TYPE_STREAMING} or
+ * {@link BluetoothHealth#CHANNEL_TYPE_ANY}.
+ */
+ public int getChannelType() {
+ return mChannelType;
+ }
+
+ /**
+ * Return the callback associated with this application configuration.
+ *
+ * @return IBluetoothHealthCallback
+ */
+ public IBluetoothHealthCallback getCallback() {
+ return mCallback;
+ }
+
+ public static final Parcelable.Creator<BluetoothHealthAppConfiguration> CREATOR =
+ new Parcelable.Creator<BluetoothHealthAppConfiguration>() {
+ public BluetoothHealthAppConfiguration createFromParcel(Parcel in) {
+ String name = in.readString();
+ int type = in.readInt();
+ int role = in.readInt();
+ int channelType = in.readInt();
+ IBluetoothHealthCallback callback =
+ IBluetoothHealthCallback.Stub.asInterface(in.readStrongBinder());
+ return new BluetoothHealthAppConfiguration(name, type, role, channelType,
+ callback);
+ }
+ public BluetoothHealthAppConfiguration[] newArray(int size) {
+ return new BluetoothHealthAppConfiguration[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mName);
+ out.writeInt(mDataType);
+ out.writeInt(mRole);
+ out.writeInt(mChannelType);
+ out.writeStrongInterface(mCallback);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 22555f0..6cd81fd 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -65,16 +65,22 @@
public static final int A2DP = 2;
/**
+ * Health Profile
+ * @hide
+ */
+ public static final int HEALTH = 3;
+
+ /**
* Input Device Profile
* @hide
*/
- public static final int INPUT_DEVICE = 3;
+ public static final int INPUT_DEVICE = 4;
/**
* PAN Profile
* @hide
*/
- public static final int PAN = 4;
+ public static final int PAN = 5;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index d25f5d0..28b09b6 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -18,7 +18,9 @@
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
/**
* System private API for talking with the Bluetooth service.
@@ -98,5 +100,17 @@
boolean connectPanDevice(in BluetoothDevice device);
boolean disconnectPanDevice(in BluetoothDevice device);
+ // HDP profile APIs
+ boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config);
+ boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
+ boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+ boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
+ int channelType);
+ boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, in ParcelFileDescriptor fd);
+ ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
+ List<BluetoothDevice> getConnectedHealthDevices();
+ List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
+ int getHealthDeviceConnectionState(in BluetoothDevice device);
+
void sendConnectionStateChange(in BluetoothDevice device, int state, int prevState);
}
diff --git a/core/java/android/bluetooth/IBluetoothHealthCallback.aidl b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
new file mode 100644
index 0000000..9fe5335
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHealthCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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 android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.os.ParcelFileDescriptor;
+
+/**
+ *@hide
+ */
+interface IBluetoothHealthCallback
+{
+ void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
+ void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
+ in BluetoothDevice device, int prevState, int newState, in ParcelFileDescriptor fd);
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index aecec66..fed6d81 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1029,6 +1029,12 @@
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
+ * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+ * registered with this method will correctly respect the
+ * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+ * Prior to that, it would be ignored and delivered to all matching registered
+ * receivers. Be careful if using this for security.</p>
+ *
* <p class="note">Note: this method <em>cannot be called from a
* {@link BroadcastReceiver} component;</em> that is, from a BroadcastReceiver
* that is declared in an application's manifest. It is okay, however, to call
@@ -1059,6 +1065,12 @@
*
* <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
*
+ * <p>As of {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}, receivers
+ * registered with this method will correctly respect the
+ * {@link Intent#setPackage(String)} specified for an Intent being broadcast.
+ * Prior to that, it would be ignored and delivered to all matching registered
+ * receivers. Be careful if using this for security.</p>
+ *
* @param receiver The BroadcastReceiver to handle the broadcast.
* @param filter Selects the Intent broadcasts to be received.
* @param broadcastPermission String naming a permissions that a
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index b7da472..7dbd6f2 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -22,5 +22,5 @@
/** @hide */
interface IIntentSender {
int send(int code, in Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver);
+ IIntentReceiver finishedReceiver, String requiredPermission);
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 007a715..4db4bdc 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -154,14 +154,47 @@
*/
public void sendIntent(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler) throws SendIntentException {
+ sendIntent(context, code, intent, onFinished, handler, null);
+ }
+
+ /**
+ * Perform the operation associated with this IntentSender, allowing the
+ * caller to specify information about the Intent to use and be notified
+ * when the send has completed.
+ *
+ * @param context The Context of the caller. This may be null if
+ * <var>intent</var> is also null.
+ * @param code Result code to supply back to the IntentSender's target.
+ * @param intent Additional Intent data. See {@link Intent#fillIn
+ * Intent.fillIn()} for information on how this is applied to the
+ * original Intent. Use null to not modify the original Intent.
+ * @param onFinished The object to call back on when the send has
+ * completed, or null for no callback.
+ * @param handler Handler identifying the thread on which the callback
+ * should happen. If null, the callback will happen from the thread
+ * pool of the process.
+ * @param requiredPermission Name of permission that a recipient of the PendingIntent
+ * is required to hold. This is only valid for broadcast intents, and
+ * corresponds to the permission argument in
+ * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+ * If null, no permission is required.
+ *
+ *
+ * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+ * is no longer allowing more intents to be sent through it.
+ */
+ public void sendIntent(Context context, int code, Intent intent,
+ OnFinished onFinished, Handler handler, String requiredPermission)
+ throws SendIntentException {
try {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
: null;
int res = mTarget.send(code, intent, resolvedType,
onFinished != null
- ? new FinishedDispatcher(this, onFinished, handler)
- : null);
+ ? new FinishedDispatcher(this, onFinished, handler)
+ : null,
+ requiredPermission);
if (res < 0) {
throw new SendIntentException();
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index c0a1d8e..454cb31 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -417,6 +417,12 @@
public boolean enabled = true;
/**
+ * For convenient access to the current enabled setting of this app.
+ * @hide
+ */
+ public int enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+
+ /**
* For convenient access to package's install location.
* @hide
*/
@@ -508,6 +514,7 @@
uid = orig.uid;
targetSdkVersion = orig.targetSdkVersion;
enabled = orig.enabled;
+ enabledSetting = orig.enabledSetting;
installLocation = orig.installLocation;
manageSpaceActivityName = orig.manageSpaceActivityName;
descriptionRes = orig.descriptionRes;
@@ -544,6 +551,7 @@
dest.writeInt(uid);
dest.writeInt(targetSdkVersion);
dest.writeInt(enabled ? 1 : 0);
+ dest.writeInt(enabledSetting);
dest.writeInt(installLocation);
dest.writeString(manageSpaceActivityName);
dest.writeString(backupAgentName);
@@ -581,6 +589,7 @@
uid = source.readInt();
targetSdkVersion = source.readInt();
enabled = source.readInt() != 0;
+ enabledSetting = source.readInt();
installLocation = source.readInt();
manageSpaceActivityName = source.readString();
backupAgentName = source.readString();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1cd8ec0..dd684cd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -224,11 +224,41 @@
*/
public static final int SIGNATURE_UNKNOWN_PACKAGE = -4;
+ /**
+ * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+ * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+ * component or application is in its default enabled state (as specified
+ * in its manifest).
+ */
public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0;
+
+ /**
+ * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+ * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+ * component or application has been explictily enabled, regardless of
+ * what it has specified in its manifest.
+ */
public static final int COMPONENT_ENABLED_STATE_ENABLED = 1;
+
+ /**
+ * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
+ * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
+ * component or application has been explicitly disabled, regardless of
+ * what it has specified in its manifest.
+ */
public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;
/**
+ * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: The
+ * user has explicitly disabled the application, regardless of what it has
+ * specified in its manifest. Because this is due to the user's request,
+ * they may re-enable it if desired through the appropriate system UI. This
+ * option currently <strong>can not</strong> be used with
+ * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
+ */
+ public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
+
+ /**
* Flag parameter for {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} to
* indicate that this package should be installed as forward locked, i.e. only the app itself
* should have access to its code and non-resource assets.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 31ad6e9..208869b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1573,7 +1573,7 @@
boolean hardwareAccelerated = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
- false);
+ owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
@@ -3128,9 +3128,11 @@
}
if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
ai.enabled = true;
- } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ } else if (p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+ || p.mSetEnabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
ai.enabled = false;
}
+ ai.enabledSetting = p.mSetEnabled;
return ai;
}
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 11068e5..1205da7 100755
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -40,6 +40,12 @@
public long cacheSize;
/**
+ * Size of the secure container on external storage holding the
+ * application's code.
+ */
+ public long externalCodeSize;
+
+ /**
* Size of the external data used by the application (e.g.,
* <sdcard>/Android/data/<app>)
*/
@@ -80,6 +86,8 @@
sb.append(dataSize);
sb.append(",cacheSize=");
sb.append(cacheSize);
+ sb.append(",externalCodeSize=");
+ sb.append(externalCodeSize);
sb.append(",externalDataSize=");
sb.append(externalDataSize);
sb.append(",externalCacheSize=");
@@ -100,6 +108,7 @@
codeSize = source.readLong();
dataSize = source.readLong();
cacheSize = source.readLong();
+ externalCodeSize = source.readLong();
externalDataSize = source.readLong();
externalCacheSize = source.readLong();
externalMediaSize = source.readLong();
@@ -111,6 +120,7 @@
codeSize = pStats.codeSize;
dataSize = pStats.dataSize;
cacheSize = pStats.cacheSize;
+ externalCodeSize = pStats.externalCodeSize;
externalDataSize = pStats.externalDataSize;
externalCacheSize = pStats.externalCacheSize;
externalMediaSize = pStats.externalMediaSize;
@@ -126,6 +136,7 @@
dest.writeLong(codeSize);
dest.writeLong(dataSize);
dest.writeLong(cacheSize);
+ dest.writeLong(externalCodeSize);
dest.writeLong(externalDataSize);
dest.writeLong(externalCacheSize);
dest.writeLong(externalMediaSize);
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index acf2f2f1..1c9285e 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -432,17 +432,17 @@
// compatible with large screens, so diddle it.
CompatibilityInfo.computeCompatibleScaling(inoutDm, inoutDm);
} else {
- inoutDm.widthPixels = inoutDm.unscaledWidthPixels;
- inoutDm.heightPixels = inoutDm.unscaledHeightPixels;
+ inoutDm.widthPixels = inoutDm.noncompatWidthPixels;
+ inoutDm.heightPixels = inoutDm.noncompatHeightPixels;
}
if (isScalingRequired()) {
float invertedRatio = applicationInvertedScale;
- inoutDm.density *= invertedRatio;
+ inoutDm.density = inoutDm.noncompatDensity * invertedRatio;
inoutDm.densityDpi = (int)((inoutDm.density*DisplayMetrics.DENSITY_DEFAULT)+.5f);
- inoutDm.scaledDensity *= invertedRatio;
- inoutDm.xdpi *= invertedRatio;
- inoutDm.ydpi *= invertedRatio;
+ inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * invertedRatio;
+ inoutDm.xdpi = inoutDm.noncompatXdpi * invertedRatio;
+ inoutDm.ydpi = inoutDm.noncompatYdpi * invertedRatio;
inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
}
@@ -471,8 +471,8 @@
* @return Returns the scaling factor for the window.
*/
public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
- final int width = dm.unscaledWidthPixels;
- final int height = dm.unscaledHeightPixels;
+ final int width = dm.noncompatWidthPixels;
+ final int height = dm.noncompatHeightPixels;
int shortSize, longSize;
if (width < height) {
shortSize = width;
@@ -532,7 +532,9 @@
sb.append(applicationDensity);
sb.append("dpi");
if (isScalingRequired()) {
- sb.append(" scaling");
+ sb.append(" ");
+ sb.append(applicationScale);
+ sb.append("x");
}
if (!supportsScreen()) {
sb.append(" resizing");
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index bd8b1a4..324c9fd 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1416,23 +1416,19 @@
}
if (metrics != null) {
mMetrics.setTo(metrics);
- // NOTE: We should re-arrange this code to create a Display
- // with the CompatibilityInfo that is used everywhere we deal
- // with the display in relation to this app, rather than
- // doing the conversion here. This impl should be okay because
- // we make sure to return a compatible display in the places
- // where there are public APIs to retrieve the display... but
- // it would be cleaner and more maintainble to just be
- // consistently dealing with a compatible display everywhere in
- // the framework.
- if (mCompatibilityInfo != null) {
- mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
- }
}
+ // NOTE: We should re-arrange this code to create a Display
+ // with the CompatibilityInfo that is used everywhere we deal
+ // with the display in relation to this app, rather than
+ // doing the conversion here. This impl should be okay because
+ // we make sure to return a compatible display in the places
+ // where there are public APIs to retrieve the display... but
+ // it would be cleaner and more maintainble to just be
+ // consistently dealing with a compatible display everywhere in
+ // the framework.
if (mCompatibilityInfo != null) {
mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
}
- mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
int configChanges = 0xfffffff;
if (config != null) {
mTmpConfig.setTo(config);
@@ -1448,6 +1444,7 @@
if (mConfiguration.locale == null) {
mConfiguration.locale = Locale.getDefault();
}
+ mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
String locale = null;
if (mConfiguration.locale != null) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 338e6c8..8a42693 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -288,7 +288,8 @@
* you can call {@link #reconnect()} to reclaim the camera.
*
* <p>This must be done before calling
- * {@link android.media.MediaRecorder#setCamera(Camera)}.
+ * {@link android.media.MediaRecorder#setCamera(Camera)}. This cannot be
+ * called after recording starts.
*
* <p>If you are not recording video, you probably do not need this method.
*
@@ -301,6 +302,11 @@
* Camera objects are locked by default unless {@link #unlock()} is
* called. Normally {@link #reconnect()} is used instead.
*
+ * <p>Since API level 13, camera is automatically locked for applications in
+ * {@link android.media.MediaRecorder#start()}. Applications can use the
+ * camera (ex: zoom) after recording starts. There is no need to call this
+ * after recording starts or stops.
+ *
* <p>If you are not recording video, you probably do not need this method.
*
* @throws RuntimeException if the camera cannot be re-locked (for
@@ -315,9 +321,10 @@
* which will re-acquire the lock and allow you to continue using the
* camera.
*
- * <p>This must be done after {@link android.media.MediaRecorder} is
- * done recording if {@link android.media.MediaRecorder#setCamera(Camera)}
- * was used.
+ * <p>Since API level 13, camera is automatically locked for applications in
+ * {@link android.media.MediaRecorder#start()}. Applications can use the
+ * camera (ex: zoom) after recording starts. There is no need to call this
+ * after recording starts or stops.
*
* <p>If you are not recording video, you probably do not need this method.
*
@@ -827,7 +834,9 @@
* <p>This method is only valid when preview is active (after
* {@link #startPreview()}). Preview will be stopped after the image is
* taken; callers must call {@link #startPreview()} again if they want to
- * re-start preview or take more pictures.
+ * re-start preview or take more pictures. This should not be called between
+ * {@link android.media.MediaRecorder#start()} and
+ * {@link android.media.MediaRecorder#stop()}.
*
* <p>After calling this method, you must not call {@link #startPreview()}
* or take another picture until the JPEG callback has returned.
@@ -2913,7 +2922,7 @@
* @return a list of current metering areas
*/
public List<Area> getMeteringAreas() {
- return splitArea(KEY_METERING_AREAS);
+ return splitArea(get(KEY_METERING_AREAS));
}
/**
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 5df2343..9bab797 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -81,4 +81,10 @@
/* Clears default preferences and permissions for the package */
void clearDefaults(String packageName);
+
+ /* Sets the current USB function. */
+ void setCurrentFunction(String function, boolean makeDefault);
+
+ /* Sets the file path for USB mass storage backing file. */
+ void setMassStorageBackingFile(String path);
}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 5994c98..67d200c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -22,12 +22,9 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.Log;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.util.HashMap;
/**
@@ -50,7 +47,7 @@
* This is a sticky broadcast for clients that includes USB connected/disconnected state,
* <ul>
* <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
- * <li> {@link #USB_CONFIGURATION} integer containing current USB configuration
+ * <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured.
* currently zero if not configured, one for configured.
* <li> {@link #USB_FUNCTION_MASS_STORAGE} boolean extra indicating whether the
* mass storage function is enabled
@@ -128,12 +125,12 @@
public static final String USB_CONNECTED = "connected";
/**
- * Integer extra containing currently set USB configuration.
+ * Boolean extra indicating whether USB is configured.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast.
*
* {@hide}
*/
- public static final String USB_CONFIGURATION = "configuration";
+ public static final String USB_CONFIGURED = "configured";
/**
* Name of the USB mass storage USB function.
@@ -388,21 +385,14 @@
}
}
- private static File getFunctionEnableFile(String function) {
- return new File("/sys/class/usb_composite/" + function + "/enable");
- }
-
- /**
- * Returns true if the specified USB function is supported by the kernel.
- * Note that a USB function maybe supported but disabled.
- *
- * @param function name of the USB function
- * @return true if the USB function is supported.
- *
- * {@hide}
- */
- public static boolean isFunctionSupported(String function) {
- return getFunctionEnableFile(function).exists();
+ private static boolean propertyContainsFunction(String property, String function) {
+ String functions = SystemProperties.get(property, "");
+ int index = functions.indexOf(function);
+ if (index < 0) return false;
+ if (index > 0 && functions.charAt(index - 1) != ',') return false;
+ int charAfter = index + function.length();
+ if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
+ return true;
}
/**
@@ -413,30 +403,38 @@
*
* {@hide}
*/
- public static boolean isFunctionEnabled(String function) {
+ public boolean isFunctionEnabled(String function) {
+ return propertyContainsFunction("sys.usb.config", function);
+ }
+
+ /**
+ * Sets the current USB function.
+ *
+ * @param function name of the USB function
+ * @param makeDefault true if this should be set as the default
+ *
+ * {@hide}
+ */
+ public void setCurrentFunction(String function, boolean makeDefault) {
try {
- FileInputStream stream = new FileInputStream(getFunctionEnableFile(function));
- boolean enabled = (stream.read() == '1');
- stream.close();
- return enabled;
- } catch (IOException e) {
- return false;
+ mService.setCurrentFunction(function, makeDefault);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setCurrentFunction", e);
}
}
/**
- * Enables or disables a USB function.
+ * Sets the file path for USB mass storage backing file.
+ *
+ * @param path backing file path
*
* {@hide}
*/
- public static boolean setFunctionEnabled(String function, boolean enable) {
+ public void setMassStorageBackingFile(String path) {
try {
- FileOutputStream stream = new FileOutputStream(getFunctionEnableFile(function));
- stream.write(enable ? '1' : '0');
- stream.close();
- return true;
- } catch (IOException e) {
- return false;
+ mService.setMassStorageBackingFile(path);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in setDefaultFunction", e);
}
}
}
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index df8cf9a..e10f218 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -47,6 +47,7 @@
private static final int DO_APP_PRIVATE_COMMAND = 100;
private static final int DO_TOGGLE_SOFT_INPUT = 105;
private static final int DO_FINISH_SESSION = 110;
+ private static final int DO_VIEW_CLICKED = 115;
HandlerCaller mCaller;
InputMethodSession mInputMethodSession;
@@ -133,6 +134,10 @@
mInputMethodSession = null;
return;
}
+ case DO_VIEW_CLICKED: {
+ mInputMethodSession.viewClicked(msg.arg1 == 1);
+ return;
+ }
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
@@ -167,7 +172,11 @@
oldSelStart, oldSelEnd, newSelStart, newSelEnd,
candidatesStart, candidatesEnd));
}
-
+
+ public void viewClicked(boolean focusChanged) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0));
+ }
+
public void updateCursor(Rect newCursor) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR,
newCursor));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index feb246e..9481a88 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -488,7 +488,15 @@
InputMethodService.this.onUpdateSelection(oldSelStart, oldSelEnd,
newSelStart, newSelEnd, candidatesStart, candidatesEnd);
}
-
+
+ @Override
+ public void viewClicked(boolean focusChanged) {
+ if (!isEnabled()) {
+ return;
+ }
+ InputMethodService.this.onViewClicked(focusChanged);
+ }
+
/**
* Call {@link InputMethodService#onUpdateCursor
* InputMethodService.onUpdateCursor()}.
@@ -1609,6 +1617,16 @@
}
/**
+ * Called when the user tapped or clicked a text view.
+ * IMEs can't rely on this method being called because this was not part of the original IME
+ * protocol, so applications with custom text editing written before this method appeared will
+ * not call to inform the IME of this interaction.
+ * @param focusChanged true if the user changed the focused view by this click.
+ */
+ public void onViewClicked(boolean focusChanged) {
+ }
+
+ /**
* Called when the application has reported a new location of its text
* cursor. This is only called if explicitly requested by the input method.
* The default implementation does nothing.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2242e9e..ce6f697 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -164,6 +164,12 @@
public static final String EXTRA_ERRORED_TETHER = "erroredArray";
/**
+ * The absence of APN..
+ * @hide
+ */
+ public static final int TYPE_NONE = -1;
+
+ /**
* The Default Mobile data connection. When active, all data traffic
* will use this connection by default.
*/
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index c49c019..445b2f7 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -117,13 +117,14 @@
PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
+ mDhcpRenewWakeLock.setReferenceCounted(false);
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//DHCP renew
if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
- //acquire a 40s wakelock to finish DHCP renewal
+ //Lock released after 40s in worst case scenario
mDhcpRenewWakeLock.acquire(40000);
sendMessage(CMD_RENEW_DHCP);
}
@@ -166,6 +167,7 @@
switch (message.what) {
case CMD_RENEW_DHCP:
Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
+ mDhcpRenewWakeLock.release();
break;
case SM_QUIT_CMD:
mContext.unregisterReceiver(mBroadcastReceiver);
@@ -268,10 +270,12 @@
/* Notify controller before starting DHCP */
mController.sendMessage(CMD_PRE_DHCP_ACTION);
transitionTo(mWaitBeforeRenewalState);
+ //mDhcpRenewWakeLock is released in WaitBeforeRenewalState
} else {
if (!runDhcp(DhcpAction.RENEW)) {
transitionTo(mStoppedState);
}
+ mDhcpRenewWakeLock.release();
}
break;
case CMD_START_DHCP:
@@ -318,6 +322,10 @@
}
return retValue;
}
+ @Override
+ public void exit() {
+ mDhcpRenewWakeLock.release();
+ }
}
private boolean runDhcp(DhcpAction dhcpAction) {
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 6f92247..a866436 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -53,6 +53,7 @@
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+ private static boolean mLinkUp;
private LinkProperties mLinkProperties;
private LinkCapabilities mLinkCapabilities;
private NetworkInfo mNetworkInfo;
@@ -74,8 +75,25 @@
mTracker = tracker;
}
- public void interfaceLinkStatusChanged(String iface, boolean up) {
- Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+ public void interfaceStatusChanged(String iface, boolean up) {
+ Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
+ }
+
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ if (mIface.equals(iface) && mLinkUp != up) {
+ Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+ mLinkUp = up;
+
+ // use DHCP
+ if (up) {
+ mTracker.reconnect();
+ } else {
+ NetworkUtils.stopDhcp(mIface);
+ mTracker.mNetworkInfo.setIsAvailable(false);
+ mTracker.mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,
+ null, null);
+ }
+ }
}
public void interfaceAdded(String iface) {
@@ -91,6 +109,7 @@
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
mLinkProperties = new LinkProperties();
mLinkCapabilities = new LinkCapabilities();
+ mLinkUp = false;
mNetworkInfo.setIsAvailable(false);
setTeardownRequested(false);
@@ -182,14 +201,11 @@
// register for notifications from NetworkManagement Service
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
- mInterfaceObserver = new InterfaceObserver(this);
- try {
- service.registerObserver(mInterfaceObserver);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not register InterfaceObserver " + e);
- }
- // connect to an ethernet interface that already exists
+ mInterfaceObserver = new InterfaceObserver(this);
+
+ // enable and try to connect to an ethernet interface that
+ // already exists
sIfaceMatch = context.getResources().getString(
com.android.internal.R.string.config_ethernet_iface_regex);
try {
@@ -197,6 +213,8 @@
for (String iface : ifaces) {
if (iface.matches(sIfaceMatch)) {
mIface = iface;
+ InterfaceConfiguration config = service.getInterfaceConfig(iface);
+ mLinkUp = config.isActive();
reconnect();
break;
}
@@ -204,6 +222,12 @@
} catch (RemoteException e) {
Log.e(TAG, "Could not get list of interfaces " + e);
}
+
+ try {
+ service.registerObserver(mInterfaceObserver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register InterfaceObserver " + e);
+ }
}
/**
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index d30b63d..4436e6e 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -23,12 +23,21 @@
*/
interface INetworkManagementEventObserver {
/**
- * Interface link status has changed.
+ * Interface configuration status has changed.
*
* @param iface The interface.
- * @param link True if link is up.
+ * @param up True if the interface has been enabled.
*/
- void interfaceLinkStatusChanged(String iface, boolean link);
+ void interfaceStatusChanged(String iface, boolean up);
+
+ /**
+ * Interface physical-layer link state has changed. For Ethernet,
+ * this method is invoked when the cable is plugged in or unplugged.
+ *
+ * @param iface The interface.
+ * @param up True if the physical link-layer connection signal is valid.
+ */
+ void interfaceLinkStateChanged(String iface, boolean up);
/**
* An interface has been added to the system
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 9230151..a45ec54 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -19,6 +19,7 @@
/** {@hide} */
oneway interface INetworkPolicyListener {
- void onRulesChanged(int uid, int uidRules);
+ void onUidRulesChanged(int uid, int uidRules);
+ void onMeteredIfacesChanged(in String[] meteredIfaces);
}
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 288112a..ae9aa05 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -18,18 +18,19 @@
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
/** {@hide} */
interface INetworkStatsService {
/** Return historical stats for traffic that matches template. */
- NetworkStatsHistory getHistoryForNetwork(int networkTemplate);
+ NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template);
/** Return historical stats for specific UID traffic that matches template. */
- NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate);
+ NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag);
/** Return usage summary for traffic that matches template. */
- NetworkStats getSummaryForNetwork(long start, long end, int networkTemplate, String subscriberId);
+ NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
/** Return usage summary per UID for traffic that matches template. */
- NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate);
+ NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
}
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
new file mode 100644
index 0000000..ccef122
--- /dev/null
+++ b/core/java/android/net/NetworkIdentity.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 android.net;
+
+import static android.net.ConnectivityManager.isNetworkTypeMobile;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.util.Objects;
+
+/**
+ * Network definition that includes strong identity. Analogous to combining
+ * {@link NetworkInfo} and an IMSI.
+ *
+ * @hide
+ */
+public class NetworkIdentity {
+ final int mType;
+ final int mSubType;
+ final String mSubscriberId;
+ final boolean mRoaming;
+
+ public NetworkIdentity(int type, int subType, String subscriberId, boolean roaming) {
+ this.mType = type;
+ this.mSubType = subType;
+ this.mSubscriberId = subscriberId;
+ this.mRoaming = roaming;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mType, mSubType, mSubscriberId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NetworkIdentity) {
+ final NetworkIdentity ident = (NetworkIdentity) obj;
+ return mType == ident.mType && mSubType == ident.mSubType
+ && Objects.equal(mSubscriberId, ident.mSubscriberId)
+ && mRoaming == ident.mRoaming;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ final String typeName = ConnectivityManager.getNetworkTypeName(mType);
+ final String subTypeName;
+ if (ConnectivityManager.isNetworkTypeMobile(mType)) {
+ subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
+ } else {
+ subTypeName = Integer.toString(mSubType);
+ }
+
+ final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
+ final String roaming = mRoaming ? ", ROAMING" : "";
+ return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
+ + scrubSubscriberId + roaming + "]";
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ public int getSubType() {
+ return mSubType;
+ }
+
+ public String getSubscriberId() {
+ return mSubscriberId;
+ }
+
+ public boolean getRoaming() {
+ return mRoaming;
+ }
+
+ /**
+ * Build a {@link NetworkIdentity} from the given {@link NetworkState},
+ * assuming that any mobile networks are using the current IMSI.
+ */
+ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
+ final int type = state.networkInfo.getType();
+ final int subType = state.networkInfo.getSubtype();
+
+ // TODO: consider moving subscriberId over to LinkCapabilities, so it
+ // comes from an authoritative source.
+
+ final String subscriberId;
+ final boolean roaming;
+ if (isNetworkTypeMobile(type)) {
+ final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ roaming = telephony.isNetworkRoaming();
+ if (state.subscriberId != null) {
+ subscriberId = state.subscriberId;
+ } else {
+ subscriberId = telephony.getSubscriberId();
+ }
+ } else {
+ subscriberId = null;
+ roaming = false;
+ }
+ return new NetworkIdentity(type, subType, subscriberId, roaming);
+ }
+
+}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 1899281..52cab30 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -16,37 +16,38 @@
package android.net;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
import android.os.Parcel;
import android.os.Parcelable;
/**
- * Policy for a specific network, including usage cycle and limits to be
- * enforced.
+ * Policy for networks matching a {@link NetworkTemplate}, including usage cycle
+ * and limits to be enforced.
*
* @hide
*/
public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
- public final int networkTemplate;
- public final String subscriberId;
+ public static final long WARNING_DISABLED = -1;
+ public static final long LIMIT_DISABLED = -1;
+
+ public final NetworkTemplate template;
public int cycleDay;
public long warningBytes;
public long limitBytes;
- public static final long WARNING_DISABLED = -1;
- public static final long LIMIT_DISABLED = -1;
+ // TODO: teach how to snooze limit for current cycle
- public NetworkPolicy(int networkTemplate, String subscriberId, int cycleDay, long warningBytes,
- long limitBytes) {
- this.networkTemplate = networkTemplate;
- this.subscriberId = subscriberId;
+ public NetworkPolicy(
+ NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes) {
+ this.template = checkNotNull(template, "missing NetworkTemplate");
this.cycleDay = cycleDay;
this.warningBytes = warningBytes;
this.limitBytes = limitBytes;
}
public NetworkPolicy(Parcel in) {
- networkTemplate = in.readInt();
- subscriberId = in.readString();
+ template = in.readParcelable(null);
cycleDay = in.readInt();
warningBytes = in.readLong();
limitBytes = in.readLong();
@@ -54,8 +55,7 @@
/** {@inheritDoc} */
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(networkTemplate);
- dest.writeString(subscriberId);
+ dest.writeParcelable(template, flags);
dest.writeInt(cycleDay);
dest.writeLong(warningBytes);
dest.writeLong(limitBytes);
@@ -81,8 +81,8 @@
@Override
public String toString() {
- return "NetworkPolicy: networkTemplate=" + networkTemplate + ", cycleDay=" + cycleDay
- + ", warningBytes=" + warningBytes + ", limitBytes=" + limitBytes;
+ return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes="
+ + warningBytes + ", limitBytes=" + limitBytes;
}
public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 0d4d9a9..593b2b7 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -16,14 +16,21 @@
package android.net;
+import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.text.format.Time.MONTH_DAY;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
import android.os.RemoteException;
import android.text.format.Time;
+import com.google.android.collect.Sets;
+
import java.io.PrintWriter;
+import java.util.HashSet;
/**
* Manager for creating and modifying network policy rules.
@@ -34,13 +41,15 @@
/** No specific network policy, use system default. */
public static final int POLICY_NONE = 0x0;
- /** Reject network usage on paid networks when application in background. */
- public static final int POLICY_REJECT_PAID_BACKGROUND = 0x1;
+ /** Reject network usage on metered networks when application in background. */
+ public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1;
/** All network traffic should be allowed. */
public static final int RULE_ALLOW_ALL = 0x0;
- /** Reject traffic on paid networks. */
- public static final int RULE_REJECT_PAID = 0x1;
+ /** Reject traffic on metered networks. */
+ public static final int RULE_REJECT_METERED = 0x1;
+
+ private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
/**
* {@link Intent} action launched when user selects {@link NetworkPolicy}
@@ -59,7 +68,7 @@
/**
* {@link Intent} extra included in {@link #ACTION_DATA_USAGE_WARNING} and
* {@link #ACTION_DATA_USAGE_LIMIT} to indicate which
- * {@link NetworkPolicy#networkTemplate} it applies to.
+ * {@link NetworkTemplate} rule it applies to.
*/
public static final String EXTRA_NETWORK_TEMPLATE =
"android.intent.extra.NETWORK_TEMPLATE";
@@ -98,7 +107,7 @@
* Set policy flags for specific UID.
*
* @param policy {@link #POLICY_NONE} or combination of flags like
- * {@link #POLICY_REJECT_PAID_BACKGROUND}.
+ * {@link #POLICY_REJECT_METERED_BACKGROUND}.
*/
public void setUidPolicy(int uid, int policy) {
try {
@@ -210,15 +219,44 @@
* usually to protect critical system services.
*/
public static boolean isUidValidForPolicy(Context context, int uid) {
- return (uid >= android.os.Process.FIRST_APPLICATION_UID
- && uid <= android.os.Process.LAST_APPLICATION_UID);
+ // first, quick-reject non-applications
+ if (uid < android.os.Process.FIRST_APPLICATION_UID
+ || uid > android.os.Process.LAST_APPLICATION_UID) {
+ return false;
+ }
+
+ if (!ALLOW_PLATFORM_APP_POLICY) {
+ final PackageManager pm = context.getPackageManager();
+ final HashSet<Signature> systemSignature;
+ try {
+ systemSignature = Sets.newHashSet(
+ pm.getPackageInfo("android", GET_SIGNATURES).signatures);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("problem finding system signature", e);
+ }
+
+ try {
+ // reject apps signed with platform cert
+ for (String packageName : pm.getPackagesForUid(uid)) {
+ final HashSet<Signature> packageSignature = Sets.newHashSet(
+ pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
+ if (packageSignature.containsAll(systemSignature)) {
+ return false;
+ }
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ // nothing found above; we can apply policy to UID
+ return true;
}
/** {@hide} */
public static void dumpPolicy(PrintWriter fout, int policy) {
fout.write("[");
- if ((policy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
- fout.write("REJECT_PAID_BACKGROUND");
+ if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
+ fout.write("REJECT_METERED_BACKGROUND");
}
fout.write("]");
}
@@ -226,8 +264,8 @@
/** {@hide} */
public static void dumpRules(PrintWriter fout, int rules) {
fout.write("[");
- if ((rules & RULE_REJECT_PAID) != 0) {
- fout.write("REJECT_PAID");
+ if ((rules & RULE_REJECT_METERED) != 0) {
+ fout.write("REJECT_METERED");
}
fout.write("]");
}
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 749039a..704111b 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -29,18 +29,27 @@
public final NetworkInfo networkInfo;
public final LinkProperties linkProperties;
public final LinkCapabilities linkCapabilities;
+ /** Currently only used by testing. */
+ public final String subscriberId;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
LinkCapabilities linkCapabilities) {
+ this(networkInfo, linkProperties, linkCapabilities, null);
+ }
+
+ public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
+ LinkCapabilities linkCapabilities, String subscriberId) {
this.networkInfo = networkInfo;
this.linkProperties = linkProperties;
this.linkCapabilities = linkCapabilities;
+ this.subscriberId = subscriberId;
}
public NetworkState(Parcel in) {
networkInfo = in.readParcelable(null);
linkProperties = in.readParcelable(null);
linkCapabilities = in.readParcelable(null);
+ subscriberId = in.readString();
}
/** {@inheritDoc} */
@@ -53,6 +62,7 @@
out.writeParcelable(networkInfo, flags);
out.writeParcelable(linkProperties, flags);
out.writeParcelable(linkCapabilities, flags);
+ out.writeString(subscriberId);
}
public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 60f740e..9d40c42 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -40,9 +40,8 @@
public static final String IFACE_ALL = null;
/** {@link #uid} value when UID details unavailable. */
public static final int UID_ALL = -1;
-
- // NOTE: data should only be accounted for once in this structure; if data
- // is broken out, the summarized version should not be included.
+ /** {@link #tag} value for without tag. */
+ public static final int TAG_NONE = 0;
/**
* {@link SystemClock#elapsedRealtime()} timestamp when this data was
@@ -52,16 +51,16 @@
public int size;
public String[] iface;
public int[] uid;
+ public int[] tag;
public long[] rx;
public long[] tx;
- // TODO: add fg/bg stats once reported by kernel
-
public NetworkStats(long elapsedRealtime, int initialSize) {
this.elapsedRealtime = elapsedRealtime;
this.size = 0;
this.iface = new String[initialSize];
this.uid = new int[initialSize];
+ this.tag = new int[initialSize];
this.rx = new long[initialSize];
this.tx = new long[initialSize];
}
@@ -71,21 +70,27 @@
size = parcel.readInt();
iface = parcel.createStringArray();
uid = parcel.createIntArray();
+ tag = parcel.createIntArray();
rx = parcel.createLongArray();
tx = parcel.createLongArray();
}
- public NetworkStats addEntry(String iface, int uid, long rx, long tx) {
+ /**
+ * Add new stats entry with given values.
+ */
+ public NetworkStats addEntry(String iface, int uid, int tag, long rx, long tx) {
if (size >= this.iface.length) {
final int newLength = Math.max(this.iface.length, 10) * 3 / 2;
this.iface = Arrays.copyOf(this.iface, newLength);
this.uid = Arrays.copyOf(this.uid, newLength);
+ this.tag = Arrays.copyOf(this.tag, newLength);
this.rx = Arrays.copyOf(this.rx, newLength);
this.tx = Arrays.copyOf(this.tx, newLength);
}
this.iface[size] = iface;
this.uid[size] = uid;
+ this.tag[size] = tag;
this.rx[size] = rx;
this.tx[size] = tx;
size++;
@@ -93,17 +98,29 @@
return this;
}
- @Deprecated
- public int length() {
- return size;
+ /**
+ * Combine given values with an existing row, or create a new row if
+ * {@link #findIndex(String, int, int)} is unable to find match. Can also be
+ * used to subtract values from existing rows.
+ */
+ public NetworkStats combineEntry(String iface, int uid, int tag, long rx, long tx) {
+ final int i = findIndex(iface, uid, tag);
+ if (i == -1) {
+ // only create new entry when positive contribution
+ addEntry(iface, uid, tag, rx, tx);
+ } else {
+ this.rx[i] += rx;
+ this.tx[i] += tx;
+ }
+ return this;
}
/**
* Find first stats index that matches the requested parameters.
*/
- public int findIndex(String iface, int uid) {
+ public int findIndex(String iface, int uid, int tag) {
for (int i = 0; i < size; i++) {
- if (equal(iface, this.iface[i]) && uid == this.uid[i]) {
+ if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
return i;
}
}
@@ -186,12 +203,13 @@
for (int i = 0; i < size; i++) {
final String iface = this.iface[i];
final int uid = this.uid[i];
+ final int tag = this.tag[i];
// find remote row that matches, and subtract
- final int j = value.findIndex(iface, uid);
+ final int j = value.findIndex(iface, uid, tag);
if (j == -1) {
// newly appearing row, return entire value
- result.addEntry(iface, uid, this.rx[i], this.tx[i]);
+ result.addEntry(iface, uid, tag, this.rx[i], this.tx[i]);
} else {
// existing row, subtract remote value
long rx = this.rx[i] - value.rx[j];
@@ -203,7 +221,7 @@
rx = Math.max(0, rx);
tx = Math.max(0, tx);
}
- result.addEntry(iface, uid, rx, tx);
+ result.addEntry(iface, uid, tag, rx, tx);
}
}
@@ -221,6 +239,7 @@
pw.print(prefix);
pw.print(" iface="); pw.print(iface[i]);
pw.print(" uid="); pw.print(uid[i]);
+ pw.print(" tag="); pw.print(tag[i]);
pw.print(" rx="); pw.print(rx[i]);
pw.print(" tx="); pw.println(tx[i]);
}
@@ -244,6 +263,7 @@
dest.writeInt(size);
dest.writeStringArray(iface);
dest.writeIntArray(uid);
+ dest.writeIntArray(tag);
dest.writeLongArray(rx);
dest.writeLongArray(tx);
}
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 5fa8e21..ff6e220 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -40,10 +40,9 @@
* @hide
*/
public class NetworkStatsHistory implements Parcelable {
- private static final int VERSION_CURRENT = 1;
+ private static final int VERSION_INIT = 1;
- // TODO: teach about zigzag encoding to use less disk space
- // TODO: teach how to convert between bucket sizes
+ // TODO: teach about varint encoding to use less disk space
public final long bucketDuration;
@@ -83,7 +82,7 @@
public NetworkStatsHistory(DataInputStream in) throws IOException {
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
+ case VERSION_INIT: {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
rx = readLongArray(in);
@@ -98,7 +97,7 @@
}
public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_INIT);
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
writeLongArray(out, rx, bucketCount);
@@ -115,6 +114,11 @@
* distribute across internal buckets, creating new buckets as needed.
*/
public void recordData(long start, long end, long rx, long tx) {
+ if (rx < 0 || tx < 0) {
+ throw new IllegalArgumentException(
+ "tried recording negative data: rx=" + rx + ", tx=" + tx);
+ }
+
// create any buckets needed by this range
ensureBuckets(start, end);
diff --git a/core/java/android/net/NetworkTemplate.aidl b/core/java/android/net/NetworkTemplate.aidl
new file mode 100644
index 0000000..3d37488
--- /dev/null
+++ b/core/java/android/net/NetworkTemplate.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.net;
+
+parcelable NetworkTemplate;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
new file mode 100644
index 0000000..9381f1d
--- /dev/null
+++ b/core/java/android/net/NetworkTemplate.java
@@ -0,0 +1,217 @@
+/*
+ * 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 android.net;
+
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.ConnectivityManager.isNetworkTypeMobile;
+import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
+import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
+import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
+import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
+import static android.telephony.TelephonyManager.getNetworkClass;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Objects;
+
+/**
+ * Template definition used to generically match {@link NetworkIdentity},
+ * usually when collecting statistics.
+ *
+ * @hide
+ */
+public class NetworkTemplate implements Parcelable {
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
+ * networks together. Only uses statistics for requested IMSI.
+ */
+ public static final int MATCH_MOBILE_ALL = 1;
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
+ * networks together that roughly meet a "3G" definition, or lower. Only
+ * uses statistics for requested IMSI.
+ */
+ public static final int MATCH_MOBILE_3G_LOWER = 2;
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
+ * networks together that meet a "4G" definition. Only uses statistics for
+ * requested IMSI.
+ */
+ public static final int MATCH_MOBILE_4G = 3;
+
+ /**
+ * Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
+ * networks together.
+ */
+ public static final int MATCH_WIFI = 4;
+
+ final int mMatchRule;
+ final String mSubscriberId;
+
+ public NetworkTemplate(int matchRule, String subscriberId) {
+ this.mMatchRule = matchRule;
+ this.mSubscriberId = subscriberId;
+ }
+
+ public NetworkTemplate(Parcel in) {
+ mMatchRule = in.readInt();
+ mSubscriberId = in.readString();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mMatchRule);
+ dest.writeString(mSubscriberId);
+ }
+
+ /** {@inheritDoc} */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ final String scrubSubscriberId = mSubscriberId != null ? "valid" : "null";
+ return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId="
+ + scrubSubscriberId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mMatchRule, mSubscriberId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NetworkTemplate) {
+ final NetworkTemplate other = (NetworkTemplate) obj;
+ return mMatchRule == other.mMatchRule
+ && Objects.equal(mSubscriberId, other.mSubscriberId);
+ }
+ return false;
+ }
+
+ public int getMatchRule() {
+ return mMatchRule;
+ }
+
+ public String getSubscriberId() {
+ return mSubscriberId;
+ }
+
+ /**
+ * Test if this network matches the given template and IMEI.
+ */
+ public boolean matches(NetworkIdentity ident) {
+ switch (mMatchRule) {
+ case MATCH_MOBILE_ALL:
+ return matchesMobile(ident);
+ case MATCH_MOBILE_3G_LOWER:
+ return matchesMobile3gLower(ident);
+ case MATCH_MOBILE_4G:
+ return matchesMobile4g(ident);
+ case MATCH_WIFI:
+ return matchesWifi(ident);
+ default:
+ throw new IllegalArgumentException("unknown network template");
+ }
+ }
+
+ /**
+ * Check if mobile network with matching IMEI. Also matches
+ * {@link #TYPE_WIMAX}.
+ */
+ private boolean matchesMobile(NetworkIdentity ident) {
+ if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+ return true;
+ } else if (ident.mType == TYPE_WIMAX) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if mobile network classified 3G or lower with matching IMEI.
+ */
+ private boolean matchesMobile3gLower(NetworkIdentity ident) {
+ if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+ switch (getNetworkClass(ident.mSubType)) {
+ case NETWORK_CLASS_UNKNOWN:
+ case NETWORK_CLASS_2_G:
+ case NETWORK_CLASS_3_G:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if mobile network classified 4G with matching IMEI. Also matches
+ * {@link #TYPE_WIMAX}.
+ */
+ private boolean matchesMobile4g(NetworkIdentity ident) {
+ if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+ switch (getNetworkClass(ident.mSubType)) {
+ case NETWORK_CLASS_4_G:
+ return true;
+ }
+ } else if (ident.mType == TYPE_WIMAX) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if matches Wi-Fi network template.
+ */
+ private boolean matchesWifi(NetworkIdentity ident) {
+ if (ident.mType == TYPE_WIFI) {
+ return true;
+ }
+ return false;
+ }
+
+ public static String getMatchRuleName(int matchRule) {
+ switch (matchRule) {
+ case MATCH_MOBILE_3G_LOWER:
+ return "MOBILE_3G_LOWER";
+ case MATCH_MOBILE_4G:
+ return "MOBILE_4G";
+ case MATCH_MOBILE_ALL:
+ return "MOBILE_ALL";
+ case MATCH_WIFI:
+ return "WIFI";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
+ public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
+ public NetworkTemplate createFromParcel(Parcel in) {
+ return new NetworkTemplate(in);
+ }
+
+ public NetworkTemplate[] newArray(int size) {
+ return new NetworkTemplate[size];
+ }
+ };
+}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 3725fa6..2b59dba 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,14 +16,18 @@
package android.net;
+import android.app.DownloadManager;
+import android.app.backup.BackupManager;
import android.content.Context;
+import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceManager;
-import dalvik.system.BlockGuard;
+import com.android.server.NetworkManagementSocketTagger;
+import dalvik.system.SocketTagger;
import java.net.Socket;
import java.net.SocketException;
@@ -42,38 +46,33 @@
public final static int UNSUPPORTED = -1;
/**
- * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
- * networks together. Only uses statistics for requested IMSI.
+ * Special UID value used when collecting {@link NetworkStatsHistory} for
+ * removed applications.
*
* @hide
*/
- public static final int TEMPLATE_MOBILE_ALL = 1;
+ public static final int UID_REMOVED = -4;
/**
- * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
- * networks together that roughly meet a "3G" definition, or lower. Only
- * uses statistics for requested IMSI.
+ * Default tag value for {@link DownloadManager} traffic.
*
* @hide
*/
- public static final int TEMPLATE_MOBILE_3G_LOWER = 2;
+ public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001;
/**
- * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
- * networks together that meet a "4G" definition. Only uses statistics for
- * requested IMSI.
+ * Default tag value for {@link MediaPlayer} traffic.
*
* @hide
*/
- public static final int TEMPLATE_MOBILE_4G = 3;
+ public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002;
/**
- * Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
- * networks together.
+ * Default tag value for {@link BackupManager} traffic.
*
* @hide
*/
- public static final int TEMPLATE_WIFI = 4;
+ public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003;
/**
* Snapshot of {@link NetworkStats} when the currently active profiling
@@ -93,12 +92,20 @@
* Changes only take effect during subsequent calls to
* {@link #tagSocket(Socket)}.
*/
+ public static void setThreadStatsTag(int tag) {
+ NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ }
+
+ /**
+ * @deprecated unsupported, will eventually be removed
+ */
+ @Deprecated
public static void setThreadStatsTag(String tag) {
- BlockGuard.setThreadSocketStatsTag(tag);
+ setThreadStatsTag(tag.hashCode());
}
public static void clearThreadStatsTag() {
- BlockGuard.setThreadSocketStatsTag(null);
+ NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
}
/**
@@ -115,12 +122,12 @@
* {@hide}
*/
public static void setThreadStatsUid(int uid) {
- BlockGuard.setThreadSocketStatsUid(uid);
+ NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
}
/** {@hide} */
public static void clearThreadStatsUid() {
- BlockGuard.setThreadSocketStatsUid(-1);
+ NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
}
/**
@@ -129,18 +136,18 @@
* parameters. When finished, call {@link #untagSocket(Socket)} to remove
* statistics parameters.
*
- * @see #setThreadStatsTag(String)
+ * @see #setThreadStatsTag(int)
* @see #setThreadStatsUid(int)
*/
public static void tagSocket(Socket socket) throws SocketException {
- BlockGuard.tagSocketFd(socket.getFileDescriptor$());
+ SocketTagger.get().tag(socket);
}
/**
* Remove any statistics parameters from the given {@link Socket}.
*/
public static void untagSocket(Socket socket) throws SocketException {
- BlockGuard.untagSocketFd(socket.getFileDescriptor$());
+ SocketTagger.get().untag(socket);
}
/**
@@ -182,17 +189,6 @@
}
}
- /** {@hide} */
- public static boolean isNetworkTemplateMobile(int networkTemplate) {
- switch (networkTemplate) {
- case TEMPLATE_MOBILE_3G_LOWER:
- case TEMPLATE_MOBILE_4G:
- case TEMPLATE_MOBILE_ALL:
- return true;
- }
- return false;
- }
-
/**
* Get the total number of packets transmitted through the mobile interface.
*
diff --git a/core/java/android/net/http/HttpResponseCache.java b/core/java/android/net/http/HttpResponseCache.java
index b5d64e4..5f65dfa 100644
--- a/core/java/android/net/http/HttpResponseCache.java
+++ b/core/java/android/net/http/HttpResponseCache.java
@@ -70,12 +70,15 @@
* the hit rate, but it may also just waste filesystem space!
*
* <p>For some applications it may be preferable to create the cache in the
- * external storage directory. Although it often has more free space, external
- * storage is optional and—even if available—can disappear during
- * use. Retrieve the external cache directory using {@link Context#getExternalCacheDir()}. If this method
- * returns null, your application should fall back to either not caching or
- * caching on non-external storage. If the external storage is removed during
- * use, the cache hit rate will drop to zero and ongoing cache reads will fail.
+ * external storage directory. <strong>There are no access controls on the
+ * external storage directory so it should not be used for caches that could
+ * contain private data.</strong> Although it often has more free space,
+ * external storage is optional and—even if available—can disappear
+ * during use. Retrieve the external cache directory using {@link
+ * Context#getExternalCacheDir()}. If this method returns null, your application
+ * should fall back to either not caching or caching on non-external storage. If
+ * the external storage is removed during use, the cache hit rate will drop to
+ * zero and ongoing cache reads will fail.
*
* <p>Flushing the cache forces its data to the filesystem. This ensures that
* all responses written to the cache will be readable the next time the
@@ -214,7 +217,7 @@
*/
public void flush() {
try {
- delegate.getCache().flush(); // TODO: fix flush() to not throw?
+ delegate.getCache().flush();
} catch (IOException ignored) {
}
}
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index 5079c23..f35002a 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -16,15 +16,19 @@
package android.net.http;
+import android.content.Context;
import android.os.Bundle;
+import android.text.format.DateFormat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
-import java.security.cert.X509Certificate;
-
import com.android.org.bouncycastle.asn1.DERObjectIdentifier;
import com.android.org.bouncycastle.asn1.x509.X509Name;
@@ -58,7 +62,7 @@
*/
private Date mValidNotAfter;
- /**
+ /**
* Bundle key names
*/
private static final String ISSUED_TO = "issued-to";
@@ -108,8 +112,10 @@
* Creates a new SSL certificate object
* @param issuedTo The entity this certificate is issued to
* @param issuedBy The entity that issued this certificate
- * @param validNotBefore The not-before date from the certificate validity period in ISO 8601 format
- * @param validNotAfter The not-after date from the certificate validity period in ISO 8601 format
+ * @param validNotBefore The not-before date from the certificate
+ * validity period in ISO 8601 format
+ * @param validNotAfter The not-after date from the certificate
+ * validity period in ISO 8601 format
* @deprecated Use {@link #SslCertificate(X509Certificate)}
*/
@Deprecated
@@ -202,9 +208,8 @@
* @return A string representation of this certificate for debugging
*/
public String toString() {
- return
- "Issued to: " + mIssuedTo.getDName() + ";\n" +
- "Issued by: " + mIssuedBy.getDName() + ";\n";
+ return ("Issued to: " + mIssuedTo.getDName() + ";\n"
+ + "Issued by: " + mIssuedBy.getDName() + ";\n");
}
/**
@@ -328,4 +333,65 @@
return mUName != null ? mUName : "";
}
}
+
+ /**
+ * Inflates the SSL certificate view (helper method).
+ * @return The resultant certificate view with issued-to, issued-by,
+ * issued-on, expires-on, and possibly other fields set.
+ * If the input certificate is null, returns null.
+ *
+ * @hide Used by Browser and Settings
+ */
+ public View inflateCertificateView(Context context) {
+ LayoutInflater factory = LayoutInflater.from(context);
+
+ View certificateView = factory.inflate(
+ com.android.internal.R.layout.ssl_certificate, null);
+
+ // issued to:
+ SslCertificate.DName issuedTo = getIssuedTo();
+ if (issuedTo != null) {
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common))
+ .setText(issuedTo.getCName());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org))
+ .setText(issuedTo.getOName());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit))
+ .setText(issuedTo.getUName());
+ }
+
+ // issued by:
+ SslCertificate.DName issuedBy = getIssuedBy();
+ if (issuedBy != null) {
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common))
+ .setText(issuedBy.getCName());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org))
+ .setText(issuedBy.getOName());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit))
+ .setText(issuedBy.getUName());
+ }
+
+ // issued on:
+ String issuedOn = formatCertificateDate(context, getValidNotBeforeDate());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on))
+ .setText(issuedOn);
+
+ // expires on:
+ String expiresOn = formatCertificateDate(context, getValidNotAfterDate());
+ ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on))
+ .setText(expiresOn);
+
+ return certificateView;
+ }
+
+ /**
+ * Formats the certificate date to a properly localized date string.
+ * @return Properly localized version of the certificate date string and
+ * the "" if it fails to localize.
+ */
+ private String formatCertificateDate(Context context, Date certificateDate) {
+ if (certificateDate == null) {
+ return "";
+ }
+ return DateFormat.getDateFormat(context).format(certificateDate);
+ }
}
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index e1b9deb..1e1cb49 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -59,36 +59,97 @@
/**
* The SSL certificate associated with the error set
*/
- SslCertificate mCertificate;
+ final SslCertificate mCertificate;
+
+ /**
+ * The URL associated with the error set.
+ */
+ final String mUrl;
/**
* Creates a new SSL error set object
* @param error The SSL error
* @param certificate The associated SSL certificate
+ * @deprecated Use {@link #SslError(int, SslCertificate, String)}
*/
+ @Deprecated
public SslError(int error, SslCertificate certificate) {
addError(error);
+ if (certificate == null) {
+ throw new NullPointerException("certificate is null.");
+ }
mCertificate = certificate;
+ mUrl = "";
}
/**
* Creates a new SSL error set object
* @param error The SSL error
* @param certificate The associated SSL certificate
+ * @deprecated Use {@link #SslError(int, X509Certificate, String)}
*/
+ @Deprecated
public SslError(int error, X509Certificate certificate) {
addError(error);
+ if (certificate == null) {
+ throw new NullPointerException("certificate is null.");
+ }
mCertificate = new SslCertificate(certificate);
+ mUrl = "";
}
/**
- * @return The SSL certificate associated with the error set
+ * Creates a new SSL error set object
+ * @param error The SSL error
+ * @param certificate The associated SSL certificate
+ * @param url The associated URL.
+ */
+ public SslError(int error, SslCertificate certificate, String url) {
+ addError(error);
+ if (certificate == null) {
+ throw new NullPointerException("certificate is null.");
+ }
+ mCertificate = certificate;
+ if (url == null) {
+ throw new NullPointerException("url is null.");
+ }
+ mUrl = url;
+ }
+
+ /**
+ * Creates a new SSL error set object
+ * @param error The SSL error
+ * @param certificate The associated SSL certificate
+ * @param url The associated URL.
+ */
+ public SslError(int error, X509Certificate certificate, String url) {
+ addError(error);
+ if (certificate == null) {
+ throw new NullPointerException("certificate is null.");
+ }
+ mCertificate = new SslCertificate(certificate);
+ if (url == null) {
+ throw new NullPointerException("url is null.");
+ }
+ mUrl = url;
+ }
+
+ /**
+ * @return The SSL certificate associated with the error set, non-null.
*/
public SslCertificate getCertificate() {
return mCertificate;
}
/**
+ * @return The URL associated with the error set, non-null.
+ * "" if one of the deprecated constructors is used.
+ */
+ public String getUrl() {
+ return mUrl;
+ }
+
+ /**
* Adds the SSL error to the error set
* @param error The SSL error to add
* @return True iff the error being added is a known SSL error
@@ -137,6 +198,7 @@
*/
public String toString() {
return "primary error: " + getPrimaryError() +
- " certificate: " + getCertificate();
+ " certificate: " + getCertificate() +
+ " on URL: " + getUrl();
}
}
diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
index 3f8b856..0c2a2fd 100755
--- a/core/java/android/nfc/INfcAdapterExtras.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -16,7 +16,6 @@
package android.nfc;
-import android.nfc.ApduList;
import android.os.Bundle;
@@ -29,4 +28,5 @@
Bundle transceive(in byte[] data_in);
int getCardEmulationRoute();
void setCardEmulationRoute(int route);
+ void authenticate(in byte[] token);
}
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 3fd26dd..0eb8cd8 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -332,6 +332,36 @@
return Uri.parse(new String(fullUri, Charsets.UTF_8));
}
+ /**
+ * Creates an NDEF record of well known type URI.
+ * TODO: Make a public API
+ * @hide
+ */
+ public static NdefRecord createUri(Uri uri) {
+ return createUri(uri.toString());
+ }
+
+ /**
+ * Creates an NDEF record of well known type URI.
+ * TODO: Make a public API
+ * @hide
+ */
+ public static NdefRecord createUri(String uriString) {
+ byte prefix = 0x0;
+ for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
+ if (uriString.startsWith(URI_PREFIX_MAP[i])) {
+ prefix = (byte) i;
+ uriString = uriString.substring(URI_PREFIX_MAP[i].length());
+ break;
+ }
+ }
+ byte[] uriBytes = uriString.getBytes(Charsets.UTF_8);
+ byte[] recordBytes = new byte[uriBytes.length + 1];
+ recordBytes[0] = prefix;
+ System.arraycopy(uriBytes, 0, recordBytes, 1, uriBytes.length);
+ return new NdefRecord(TNF_WELL_KNOWN, RTD_URI, new byte[0], recordBytes);
+ }
+
private static byte[] concat(byte[]... arrays) {
int length = 0;
for (byte[] array : arrays) {
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 54583d6..a73067a 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -313,14 +313,16 @@
*/
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("TAG ")
- .append("uid = ")
- .append(mId)
- .append(" Tech [");
- for (int i : mTechList) {
- sb.append(i)
- .append(", ");
+ StringBuilder sb = new StringBuilder("TAG: Tech [");
+ String[] techList = getTechList();
+ int length = techList.length;
+ for (int i = 0; i < length; i++) {
+ sb.append(techList[i]);
+ if (i < length - 1) {
+ sb.append(", ");
+ }
}
+ sb.append("]");
return sb.toString();
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1b28aa2..6c7c58d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -278,6 +278,16 @@
/**
* Current version under development.
+ *
+ * <p>Applications targeting this or a later release will get these
+ * new changes in behavior:</p>
+ * <ul>
+ * <li> 2d drawing hardware acceleration is now turned on by default.
+ * You can use
+ * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
+ * to turn it off if needed, although this is strongly discouraged since
+ * it will result in poor performance on larger screen devices.
+ * </ul>
*/
public static final int ICE_CREAM_SANDWICH = CUR_DEVELOPMENT;
}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index f17a6f2..c9b6121 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -59,6 +59,11 @@
void setInterfaceConfig(String iface, in InterfaceConfiguration cfg);
/**
+ * Clear all IP addresses on the specified interface
+ */
+ void clearInterfaceAddresses(String iface);
+
+ /**
* Retrieves the network routes currently configured on the specified
* interface
*/
@@ -168,21 +173,6 @@
void detachPppd(String tty);
/**
- * Turn on USB RNDIS support - this will turn off thinks like adb/mass-storage
- */
- void startUsbRNDIS();
-
- /**
- * Turn off USB RNDIS support
- */
- void stopUsbRNDIS();
-
- /**
- * Check the status of USB RNDIS support
- */
- boolean isUsbRNDISStarted();
-
- /**
* Start Wifi Access Point
*/
void startAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
@@ -220,6 +210,21 @@
NetworkStats getNetworkStatsUidDetail(int uid);
/**
+ * Set quota for an interface.
+ */
+ void setInterfaceQuota(String iface, long quota);
+
+ /**
+ * Remove quota for an interface.
+ */
+ void removeInterfaceQuota(String iface);
+
+ /**
+ * Control network activity of a UID over interfaces with a quota limit.
+ */
+ void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
+
+ /**
* Configures bandwidth throttling on an interface.
*/
void setInterfaceThrottle(String iface, int rxKbps, int txKbps);
@@ -236,4 +241,6 @@
*/
int getInterfaceTxThrottle(String iface);
+ void setBandwidthControlEnabled(boolean enabled);
+
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a17983a..21373ec 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -313,8 +313,8 @@
*/
public void release(int flags) {
synchronized (mToken) {
- mHandler.removeCallbacks(mReleaser);
if (!mRefCounted || --mCount == 0) {
+ mHandler.removeCallbacks(mReleaser);
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index c2dc8ae..9302060 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -655,6 +655,26 @@
}
return _result;
}
+
+ /*
+ * Returns the filesystem path of a mounted secure container.
+ */
+ public String getSecureContainerFilesystemPath(String id) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ String _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(id);
+ mRemote.transact(Stub.TRANSACTION_getSecureContainerFilesystemPath, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readString();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
}
private static final String DESCRIPTOR = "IMountService";
@@ -719,6 +739,8 @@
static final int TRANSACTION_getVolumeList = IBinder.FIRST_CALL_TRANSACTION + 29;
+ static final int TRANSACTION_getSecureContainerFilesystemPath = IBinder.FIRST_CALL_TRANSACTION + 30;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1031,6 +1053,15 @@
reply.writeParcelableArray(result, 0);
return true;
}
+ case TRANSACTION_getSecureContainerFilesystemPath: {
+ data.enforceInterface(DESCRIPTOR);
+ String id;
+ id = data.readString();
+ String path = getSecureContainerFilesystemPath(id);
+ reply.writeNoException();
+ reply.writeString(path);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -1210,4 +1241,6 @@
* Returns list of all mountable volumes.
*/
public Parcelable[] getVolumeList() throws RemoteException;
+
+ public String getSecureContainerFilesystemPath(String id) throws RemoteException;
}
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
index 56c4f7a..128b697 100644
--- a/core/java/android/pim/EventRecurrence.java
+++ b/core/java/android/pim/EventRecurrence.java
@@ -18,36 +18,18 @@
import android.text.TextUtils;
import android.text.format.Time;
+import android.util.Log;
+import android.util.TimeFormatException;
import java.util.Calendar;
+import java.util.HashMap;
-public class EventRecurrence
-{
- /**
- * Thrown when a recurrence string provided can not be parsed according
- * to RFC2445.
- */
- public static class InvalidFormatException extends RuntimeException
- {
- InvalidFormatException(String s) {
- super(s);
- }
- }
+/**
+ * Event recurrence utility functions.
+ */
+public class EventRecurrence {
+ private static String TAG = "EventRecur";
- public EventRecurrence()
- {
- wkst = MO;
- }
-
- /**
- * Parse an iCalendar/RFC2445 recur type according to Section 4.3.10.
- */
- public native void parse(String recur);
-
- public void setStartDate(Time date) {
- startDate = date;
- }
-
public static final int SECONDLY = 1;
public static final int MINUTELY = 2;
public static final int HOURLY = 3;
@@ -64,13 +46,15 @@
public static final int FR = 0x00200000;
public static final int SA = 0x00400000;
- public Time startDate;
- public int freq;
+ public Time startDate; // set by setStartDate(), not parse()
+
+ public int freq; // SECONDLY, MINUTELY, etc.
public String until;
public int count;
public int interval;
- public int wkst;
+ public int wkst; // SU, MO, TU, etc.
+ /* lists with zero entries may be null references */
public int[] bysecond;
public int bysecondCount;
public int[] byminute;
@@ -79,7 +63,7 @@
public int byhourCount;
public int[] byday;
public int[] bydayNum;
- public int bydayCount;
+ public int bydayCount;
public int[] bymonthday;
public int bymonthdayCount;
public int[] byyearday;
@@ -91,6 +75,91 @@
public int[] bysetpos;
public int bysetposCount;
+ /** maps a part string to a parser object */
+ private static HashMap<String,PartParser> sParsePartMap;
+ static {
+ sParsePartMap = new HashMap<String,PartParser>();
+ sParsePartMap.put("FREQ", new ParseFreq());
+ sParsePartMap.put("UNTIL", new ParseUntil());
+ sParsePartMap.put("COUNT", new ParseCount());
+ sParsePartMap.put("INTERVAL", new ParseInterval());
+ sParsePartMap.put("BYSECOND", new ParseBySecond());
+ sParsePartMap.put("BYMINUTE", new ParseByMinute());
+ sParsePartMap.put("BYHOUR", new ParseByHour());
+ sParsePartMap.put("BYDAY", new ParseByDay());
+ sParsePartMap.put("BYMONTHDAY", new ParseByMonthDay());
+ sParsePartMap.put("BYYEARDAY", new ParseByYearDay());
+ sParsePartMap.put("BYWEEKNO", new ParseByWeekNo());
+ sParsePartMap.put("BYMONTH", new ParseByMonth());
+ sParsePartMap.put("BYSETPOS", new ParseBySetPos());
+ sParsePartMap.put("WKST", new ParseWkst());
+ }
+
+ /* values for bit vector that keeps track of what we have already seen */
+ private static final int PARSED_FREQ = 1 << 0;
+ private static final int PARSED_UNTIL = 1 << 1;
+ private static final int PARSED_COUNT = 1 << 2;
+ private static final int PARSED_INTERVAL = 1 << 3;
+ private static final int PARSED_BYSECOND = 1 << 4;
+ private static final int PARSED_BYMINUTE = 1 << 5;
+ private static final int PARSED_BYHOUR = 1 << 6;
+ private static final int PARSED_BYDAY = 1 << 7;
+ private static final int PARSED_BYMONTHDAY = 1 << 8;
+ private static final int PARSED_BYYEARDAY = 1 << 9;
+ private static final int PARSED_BYWEEKNO = 1 << 10;
+ private static final int PARSED_BYMONTH = 1 << 11;
+ private static final int PARSED_BYSETPOS = 1 << 12;
+ private static final int PARSED_WKST = 1 << 13;
+
+ /** maps a FREQ value to an integer constant */
+ private static final HashMap<String,Integer> sParseFreqMap = new HashMap<String,Integer>();
+ static {
+ sParseFreqMap.put("SECONDLY", SECONDLY);
+ sParseFreqMap.put("MINUTELY", MINUTELY);
+ sParseFreqMap.put("HOURLY", HOURLY);
+ sParseFreqMap.put("DAILY", DAILY);
+ sParseFreqMap.put("WEEKLY", WEEKLY);
+ sParseFreqMap.put("MONTHLY", MONTHLY);
+ sParseFreqMap.put("YEARLY", YEARLY);
+ }
+
+ /** maps a two-character weekday string to an integer constant */
+ private static final HashMap<String,Integer> sParseWeekdayMap = new HashMap<String,Integer>();
+ static {
+ sParseWeekdayMap.put("SU", SU);
+ sParseWeekdayMap.put("MO", MO);
+ sParseWeekdayMap.put("TU", TU);
+ sParseWeekdayMap.put("WE", WE);
+ sParseWeekdayMap.put("TH", TH);
+ sParseWeekdayMap.put("FR", FR);
+ sParseWeekdayMap.put("SA", SA);
+ }
+
+ /** If set, allow lower-case recurrence rule strings. Minor performance impact. */
+ private static final boolean ALLOW_LOWER_CASE = false;
+
+ /** If set, validate the value of UNTIL parts. Minor performance impact. */
+ private static final boolean VALIDATE_UNTIL = false;
+
+ /** If set, require that only one of {UNTIL,COUNT} is present. Breaks compat w/ old parser. */
+ private static final boolean ONLY_ONE_UNTIL_COUNT = false;
+
+
+ /**
+ * Thrown when a recurrence string provided can not be parsed according
+ * to RFC2445.
+ */
+ public static class InvalidFormatException extends RuntimeException {
+ InvalidFormatException(String s) {
+ super(s);
+ }
+ }
+
+
+ public void setStartDate(Time date) {
+ startDate = date;
+ }
+
/**
* Converts one of the Calendar.SUNDAY constants to the SU, MO, etc.
* constants. btw, I think we should switch to those here too, to
@@ -118,7 +187,7 @@
throw new RuntimeException("bad day of week: " + day);
}
}
-
+
public static int timeDay2Day(int day)
{
switch (day)
@@ -191,16 +260,16 @@
throw new RuntimeException("bad day of week: " + day);
}
}
-
+
/**
* Converts one of the internal day constants (SU, MO, etc.) to the
* two-letter string representing that constant.
- *
- * @throws IllegalArgumentException Thrown if the day argument is not one of
- * the defined day constants.
- *
+ *
* @param day one the internal constants SU, MO, etc.
* @return the two-letter string for the day ("SU", "MO", etc.)
+ *
+ * @throws IllegalArgumentException Thrown if the day argument is not one of
+ * the defined day constants.
*/
private static String day2String(int day) {
switch (day) {
@@ -283,7 +352,7 @@
s.append(";UNTIL=");
s.append(until);
}
-
+
if (this.count != 0) {
s.append(";COUNT=");
s.append(this.count);
@@ -323,36 +392,501 @@
return s.toString();
}
-
+
public boolean repeatsOnEveryWeekDay() {
if (this.freq != WEEKLY) {
- return false;
+ return false;
}
-
+
int count = this.bydayCount;
if (count != 5) {
return false;
}
-
+
for (int i = 0 ; i < count ; i++) {
int day = byday[i];
if (day == SU || day == SA) {
return false;
}
}
-
+
return true;
}
-
+
+ /**
+ * Determines whether this rule specifies a simple monthly rule by weekday, such as
+ * "FREQ=MONTHLY;BYDAY=3TU" (the 3rd Tuesday of every month).
+ * <p>
+ * Negative days, e.g. "FREQ=MONTHLY;BYDAY=-1TU" (the last Tuesday of every month),
+ * will cause "false" to be returned.
+ * <p>
+ * Rules that fire every week, such as "FREQ=MONTHLY;BYDAY=TU" (every Tuesday of every
+ * month) will cause "false" to be returned. (Note these are usually expressed as
+ * WEEKLY rules, and hence are uncommon.)
+ *
+ * @return true if this rule is of the appropriate form
+ */
public boolean repeatsMonthlyOnDayCount() {
if (this.freq != MONTHLY) {
return false;
}
-
+
if (bydayCount != 1 || bymonthdayCount != 0) {
return false;
}
-
+
+ if (bydayNum[0] <= 0) {
+ return false;
+ }
+
return true;
}
+
+ /**
+ * Determines whether two integer arrays contain identical elements.
+ * <p>
+ * The native implementation over-allocated the arrays (and may have stuff left over from
+ * a previous run), so we can't just check the arrays -- the separately-maintained count
+ * field also matters. We assume that a null array will have a count of zero, and that the
+ * array can hold as many elements as the associated count indicates.
+ * <p>
+ * TODO: replace this with Arrays.equals() when the old parser goes away.
+ */
+ private static boolean arraysEqual(int[] array1, int count1, int[] array2, int count2) {
+ if (count1 != count2) {
+ return false;
+ }
+
+ for (int i = 0; i < count1; i++) {
+ if (array1[i] != array2[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof EventRecurrence)) {
+ return false;
+ }
+
+ EventRecurrence er = (EventRecurrence) obj;
+ return (startDate == null ?
+ er.startDate == null : Time.compare(startDate, er.startDate) == 0) &&
+ freq == er.freq &&
+ (until == null ? er.until == null : until.equals(er.until)) &&
+ count == er.count &&
+ interval == er.interval &&
+ wkst == er.wkst &&
+ arraysEqual(bysecond, bysecondCount, er.bysecond, er.bysecondCount) &&
+ arraysEqual(byminute, byminuteCount, er.byminute, er.byminuteCount) &&
+ arraysEqual(byhour, byhourCount, er.byhour, er.byhourCount) &&
+ arraysEqual(byday, bydayCount, er.byday, er.bydayCount) &&
+ arraysEqual(bydayNum, bydayCount, er.bydayNum, er.bydayCount) &&
+ arraysEqual(bymonthday, bymonthdayCount, er.bymonthday, er.bymonthdayCount) &&
+ arraysEqual(byyearday, byyeardayCount, er.byyearday, er.byyeardayCount) &&
+ arraysEqual(byweekno, byweeknoCount, er.byweekno, er.byweeknoCount) &&
+ arraysEqual(bymonth, bymonthCount, er.bymonth, er.bymonthCount) &&
+ arraysEqual(bysetpos, bysetposCount, er.bysetpos, er.bysetposCount);
+ }
+
+ @Override public int hashCode() {
+ // We overrode equals, so we must override hashCode(). Nobody seems to need this though.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Resets parser-modified fields to their initial state. Does not alter startDate.
+ * <p>
+ * The original parser always set all of the "count" fields, "wkst", and "until",
+ * essentially allowing the same object to be used multiple times by calling parse().
+ * It's unclear whether this behavior was intentional. For now, be paranoid and
+ * preserve the existing behavior by resetting the fields.
+ * <p>
+ * We don't need to touch the integer arrays; they will either be ignored or
+ * overwritten. The "startDate" field is not set by the parser, so we ignore it here.
+ */
+ private void resetFields() {
+ until = null;
+ freq = count = interval = bysecondCount = byminuteCount = byhourCount =
+ bydayCount = bymonthdayCount = byyeardayCount = byweeknoCount = bymonthCount =
+ bysetposCount = 0;
+ }
+
+ /**
+ * Parses an rfc2445 recurrence rule string into its component pieces. Attempting to parse
+ * malformed input will result in an EventRecurrence.InvalidFormatException.
+ *
+ * @param recur The recurrence rule to parse (in un-folded form).
+ */
+ public void parse(String recur) {
+ /*
+ * From RFC 2445 section 4.3.10:
+ *
+ * recur = "FREQ"=freq *(
+ * ; either UNTIL or COUNT may appear in a 'recur',
+ * ; but UNTIL and COUNT MUST NOT occur in the same 'recur'
+ *
+ * ( ";" "UNTIL" "=" enddate ) /
+ * ( ";" "COUNT" "=" 1*DIGIT ) /
+ *
+ * ; the rest of these keywords are optional,
+ * ; but MUST NOT occur more than once
+ *
+ * ( ";" "INTERVAL" "=" 1*DIGIT ) /
+ * ( ";" "BYSECOND" "=" byseclist ) /
+ * ( ";" "BYMINUTE" "=" byminlist ) /
+ * ( ";" "BYHOUR" "=" byhrlist ) /
+ * ( ";" "BYDAY" "=" bywdaylist ) /
+ * ( ";" "BYMONTHDAY" "=" bymodaylist ) /
+ * ( ";" "BYYEARDAY" "=" byyrdaylist ) /
+ * ( ";" "BYWEEKNO" "=" bywknolist ) /
+ * ( ";" "BYMONTH" "=" bymolist ) /
+ * ( ";" "BYSETPOS" "=" bysplist ) /
+ * ( ";" "WKST" "=" weekday ) /
+ * ( ";" x-name "=" text )
+ * )
+ *
+ * Examples:
+ * FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
+ * FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8
+ *
+ * Strategy:
+ * (1) Split the string at ';' boundaries to get an array of rule "parts".
+ * (2) For each part, find substrings for left/right sides of '=' (name/value).
+ * (3) Call a <name>-specific parsing function to parse the <value> into an
+ * output field.
+ *
+ * By keeping track of which names we've seen in a bit vector, we can verify the
+ * constraints indicated above (FREQ appears first, none of them appear more than once --
+ * though x-[name] would require special treatment), and we have either UNTIL or COUNT
+ * but not both.
+ *
+ * In general, RFC 2445 property names (e.g. "FREQ") and enumerations ("TU") must
+ * be handled in a case-insensitive fashion, but case may be significant for other
+ * properties. We don't have any case-sensitive values in RRULE, except possibly
+ * for the custom "X-" properties, but we ignore those anyway. Thus, we can trivially
+ * convert the entire string to upper case and then use simple comparisons.
+ *
+ * Differences from previous version:
+ * - allows lower-case property and enumeration values [optional]
+ * - enforces that FREQ appears first
+ * - enforces that only one of UNTIL and COUNT may be specified
+ * - allows (but ignores) X-* parts
+ * - improved validation on various values (e.g. UNTIL timestamps)
+ * - error messages are more specific
+ */
+
+ /* TODO: replace with "if (freq != 0) throw" if nothing requires this */
+ resetFields();
+
+ int parseFlags = 0;
+ String[] parts;
+ if (ALLOW_LOWER_CASE) {
+ parts = recur.toUpperCase().split(";");
+ } else {
+ parts = recur.split(";");
+ }
+ for (String part : parts) {
+ int equalIndex = part.indexOf('=');
+ if (equalIndex <= 0) {
+ /* no '=' or no LHS */
+ throw new InvalidFormatException("Missing LHS in " + part);
+ }
+
+ String lhs = part.substring(0, equalIndex);
+ String rhs = part.substring(equalIndex + 1);
+ if (rhs.length() == 0) {
+ throw new InvalidFormatException("Missing RHS in " + part);
+ }
+
+ /*
+ * In lieu of a "switch" statement that allows string arguments, we use a
+ * map from strings to parsing functions.
+ */
+ PartParser parser = sParsePartMap.get(lhs);
+ if (parser == null) {
+ if (lhs.startsWith("X-")) {
+ //Log.d(TAG, "Ignoring custom part " + lhs);
+ continue;
+ }
+ throw new InvalidFormatException("Couldn't find parser for " + lhs);
+ } else {
+ int flag = parser.parsePart(rhs, this);
+ if ((parseFlags & flag) != 0) {
+ throw new InvalidFormatException("Part " + lhs + " was specified twice");
+ }
+ if (parseFlags == 0 && flag != PARSED_FREQ) {
+ throw new InvalidFormatException("FREQ must be specified first");
+ }
+ parseFlags |= flag;
+ }
+ }
+
+ // If not specified, week starts on Monday.
+ if ((parseFlags & PARSED_WKST) == 0) {
+ wkst = MO;
+ }
+
+ // FREQ is mandatory.
+ if ((parseFlags & PARSED_FREQ) == 0) {
+ throw new InvalidFormatException("Must specify a FREQ value");
+ }
+
+ // Can't have both UNTIL and COUNT.
+ if ((parseFlags & (PARSED_UNTIL | PARSED_COUNT)) == (PARSED_UNTIL | PARSED_COUNT)) {
+ if (ONLY_ONE_UNTIL_COUNT) {
+ throw new InvalidFormatException("Must not specify both UNTIL and COUNT: " + recur);
+ } else {
+ Log.w(TAG, "Warning: rrule has both UNTIL and COUNT: " + recur);
+ }
+ }
+ }
+
+ /**
+ * Base class for the RRULE part parsers.
+ */
+ abstract static class PartParser {
+ /**
+ * Parses a single part.
+ *
+ * @param value The right-hand-side of the part.
+ * @param er The EventRecurrence into which the result is stored.
+ * @return A bit value indicating which part was parsed.
+ */
+ public abstract int parsePart(String value, EventRecurrence er);
+
+ /**
+ * Parses an integer, with range-checking.
+ *
+ * @param str The string to parse.
+ * @param minVal Minimum allowed value.
+ * @param maxVal Maximum allowed value.
+ * @param allowZero Is 0 allowed?
+ * @return The parsed value.
+ */
+ public static int parseIntRange(String str, int minVal, int maxVal, boolean allowZero) {
+ try {
+ if (str.charAt(0) == '+') {
+ // Integer.parseInt does not allow a leading '+', so skip it manually.
+ str = str.substring(1);
+ }
+ int val = Integer.parseInt(str);
+ if (val < minVal || val > maxVal || (val == 0 && !allowZero)) {
+ throw new InvalidFormatException("Integer value out of range: " + str);
+ }
+ return val;
+ } catch (NumberFormatException nfe) {
+ throw new InvalidFormatException("Invalid integer value: " + str);
+ }
+ }
+
+ /**
+ * Parses a comma-separated list of integers, with range-checking.
+ *
+ * @param listStr The string to parse.
+ * @param minVal Minimum allowed value.
+ * @param maxVal Maximum allowed value.
+ * @param allowZero Is 0 allowed?
+ * @return A new array with values, sized to hold the exact number of elements.
+ */
+ public static int[] parseNumberList(String listStr, int minVal, int maxVal,
+ boolean allowZero) {
+ int[] values;
+
+ if (listStr.indexOf(",") < 0) {
+ // Common case: only one entry, skip split() overhead.
+ values = new int[1];
+ values[0] = parseIntRange(listStr, minVal, maxVal, allowZero);
+ } else {
+ String[] valueStrs = listStr.split(",");
+ int len = valueStrs.length;
+ values = new int[len];
+ for (int i = 0; i < len; i++) {
+ values[i] = parseIntRange(valueStrs[i], minVal, maxVal, allowZero);
+ }
+ }
+ return values;
+ }
+ }
+
+ /** parses FREQ={SECONDLY,MINUTELY,...} */
+ private static class ParseFreq extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ Integer freq = sParseFreqMap.get(value);
+ if (freq == null) {
+ throw new InvalidFormatException("Invalid FREQ value: " + value);
+ }
+ er.freq = freq;
+ return PARSED_FREQ;
+ }
+ }
+ /** parses UNTIL=enddate, e.g. "19970829T021400" */
+ private static class ParseUntil extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ if (VALIDATE_UNTIL) {
+ try {
+ // Parse the time to validate it. The result isn't retained.
+ Time until = new Time();
+ until.parse(value);
+ } catch (TimeFormatException tfe) {
+ throw new InvalidFormatException("Invalid UNTIL value: " + value);
+ }
+ }
+ er.until = value;
+ return PARSED_UNTIL;
+ }
+ }
+ /** parses COUNT=[non-negative-integer] */
+ private static class ParseCount extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ er.count = parseIntRange(value, 0, Integer.MAX_VALUE, true);
+ return PARSED_COUNT;
+ }
+ }
+ /** parses INTERVAL=[non-negative-integer] */
+ private static class ParseInterval extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ er.interval = parseIntRange(value, 1, Integer.MAX_VALUE, false);
+ return PARSED_INTERVAL;
+ }
+ }
+ /** parses BYSECOND=byseclist */
+ private static class ParseBySecond extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] bysecond = parseNumberList(value, 0, 59, true);
+ er.bysecond = bysecond;
+ er.bysecondCount = bysecond.length;
+ return PARSED_BYSECOND;
+ }
+ }
+ /** parses BYMINUTE=byminlist */
+ private static class ParseByMinute extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] byminute = parseNumberList(value, 0, 59, true);
+ er.byminute = byminute;
+ er.byminuteCount = byminute.length;
+ return PARSED_BYMINUTE;
+ }
+ }
+ /** parses BYHOUR=byhrlist */
+ private static class ParseByHour extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] byhour = parseNumberList(value, 0, 23, true);
+ er.byhour = byhour;
+ er.byhourCount = byhour.length;
+ return PARSED_BYHOUR;
+ }
+ }
+ /** parses BYDAY=bywdaylist, e.g. "1SU,-1SU" */
+ private static class ParseByDay extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] byday;
+ int[] bydayNum;
+ int bydayCount;
+
+ if (value.indexOf(",") < 0) {
+ /* only one entry, skip split() overhead */
+ bydayCount = 1;
+ byday = new int[1];
+ bydayNum = new int[1];
+ parseWday(value, byday, bydayNum, 0);
+ } else {
+ String[] wdays = value.split(",");
+ int len = wdays.length;
+ bydayCount = len;
+ byday = new int[len];
+ bydayNum = new int[len];
+ for (int i = 0; i < len; i++) {
+ parseWday(wdays[i], byday, bydayNum, i);
+ }
+ }
+ er.byday = byday;
+ er.bydayNum = bydayNum;
+ er.bydayCount = bydayCount;
+ return PARSED_BYDAY;
+ }
+
+ /** parses [int]weekday, putting the pieces into parallel array entries */
+ private static void parseWday(String str, int[] byday, int[] bydayNum, int index) {
+ int wdayStrStart = str.length() - 2;
+ String wdayStr;
+
+ if (wdayStrStart > 0) {
+ /* number is included; parse it out and advance to weekday */
+ String numPart = str.substring(0, wdayStrStart);
+ int num = parseIntRange(numPart, -53, 53, false);
+ bydayNum[index] = num;
+ wdayStr = str.substring(wdayStrStart);
+ } else {
+ /* just the weekday string */
+ wdayStr = str;
+ }
+ Integer wday = sParseWeekdayMap.get(wdayStr);
+ if (wday == null) {
+ throw new InvalidFormatException("Invalid BYDAY value: " + str);
+ }
+ byday[index] = wday;
+ }
+ }
+ /** parses BYMONTHDAY=bymodaylist */
+ private static class ParseByMonthDay extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] bymonthday = parseNumberList(value, -31, 31, false);
+ er.bymonthday = bymonthday;
+ er.bymonthdayCount = bymonthday.length;
+ return PARSED_BYMONTHDAY;
+ }
+ }
+ /** parses BYYEARDAY=byyrdaylist */
+ private static class ParseByYearDay extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] byyearday = parseNumberList(value, -366, 366, false);
+ er.byyearday = byyearday;
+ er.byyeardayCount = byyearday.length;
+ return PARSED_BYYEARDAY;
+ }
+ }
+ /** parses BYWEEKNO=bywknolist */
+ private static class ParseByWeekNo extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] byweekno = parseNumberList(value, -53, 53, false);
+ er.byweekno = byweekno;
+ er.byweeknoCount = byweekno.length;
+ return PARSED_BYWEEKNO;
+ }
+ }
+ /** parses BYMONTH=bymolist */
+ private static class ParseByMonth extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] bymonth = parseNumberList(value, 1, 12, false);
+ er.bymonth = bymonth;
+ er.bymonthCount = bymonth.length;
+ return PARSED_BYMONTH;
+ }
+ }
+ /** parses BYSETPOS=bysplist */
+ private static class ParseBySetPos extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ int[] bysetpos = parseNumberList(value, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
+ er.bysetpos = bysetpos;
+ er.bysetposCount = bysetpos.length;
+ return PARSED_BYSETPOS;
+ }
+ }
+ /** parses WKST={SU,MO,...} */
+ private static class ParseWkst extends PartParser {
+ @Override public int parsePart(String value, EventRecurrence er) {
+ Integer wkst = sParseWeekdayMap.get(value);
+ if (wkst == null) {
+ throw new InvalidFormatException("Invalid WKST value: " + value);
+ }
+ er.wkst = wkst;
+ return PARSED_WKST;
+ }
+ }
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 14e7bed..c90de17 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -16,9 +16,6 @@
package android.preference;
-import com.android.internal.util.XmlUtils;
-
-import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentBreadCrumbs;
import android.app.FragmentManager;
@@ -26,7 +23,6 @@
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -41,23 +37,26 @@
import android.util.Xml;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* This is the base class for an activity to show a hierarchy of preferences
* to the user. Prior to {@link android.os.Build.VERSION_CODES#HONEYCOMB}
@@ -66,7 +65,7 @@
* class. If you are using PreferenceActivity in its old mode, the documentation
* there applies to the deprecated APIs here.
*
- * <p>This activity shows one or more headers of preferences, each of with
+ * <p>This activity shows one or more headers of preferences, each of which
* is associated with a {@link PreferenceFragment} to display the preferences
* of that header. The actual layout and display of these associations can
* however vary; currently there are two major approaches it may take:
@@ -117,7 +116,6 @@
public abstract class PreferenceActivity extends ListActivity implements
PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback {
- private static final String TAG = "PreferenceActivity";
// Constants for state save/restore
private static final String HEADERS_TAG = ":android:headers";
@@ -182,8 +180,6 @@
private final ArrayList<Header> mHeaders = new ArrayList<Header>();
- private HeaderAdapter mAdapter;
-
private FrameLayout mListFooter;
private ViewGroup mPrefsContainer;
@@ -222,8 +218,8 @@
ArrayList<Header> oldHeaders = new ArrayList<Header>(mHeaders);
mHeaders.clear();
onBuildHeaders(mHeaders);
- if (mAdapter != null) {
- mAdapter.notifyDataSetChanged();
+ if (mAdapter instanceof BaseAdapter) {
+ ((BaseAdapter) mAdapter).notifyDataSetChanged();
}
Header header = onGetNewHeader();
if (header != null && header.fragment != null) {
@@ -387,6 +383,7 @@
public Bundle extras;
public Header() {
+ // Empty
}
/**
@@ -521,7 +518,7 @@
if (headers != null) {
mHeaders.addAll(headers);
int curHeader = savedInstanceState.getInt(CUR_HEADER_TAG,
- (int)HEADER_ID_UNDEFINED);
+ (int) HEADER_ID_UNDEFINED);
if (curHeader >= 0 && curHeader < mHeaders.size()) {
setSelectedHeader(mHeaders.get(curHeader));
}
@@ -567,8 +564,7 @@
findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE);
mPrefsContainer.setVisibility(View.VISIBLE);
} else if (mHeaders.size() > 0) {
- mAdapter = new HeaderAdapter(this, mHeaders);
- setListAdapter(mAdapter);
+ setListAdapter(new HeaderAdapter(this, mHeaders));
if (!mSinglePane) {
// Multi-pane.
getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
@@ -715,6 +711,7 @@
* @param target The list in which to place the headers.
*/
public void onBuildHeaders(List<Header> target) {
+ // Should be overloaded by subclasses
}
/**
@@ -743,6 +740,7 @@
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
+ // Parse next until start tag is found
}
String nodeName = parser.getName();
@@ -951,7 +949,8 @@
super.onListItemClick(l, v, position, id);
if (mAdapter != null) {
- onHeaderClick(mHeaders.get(position), position);
+ Object item = mAdapter.getItem(position);
+ if (item instanceof Header) onHeaderClick((Header) item, position);
}
}
@@ -993,7 +992,7 @@
* @param fragmentName The name of the fragment to display.
* @param args Optional arguments to supply to the fragment.
* @param titleRes Optional resource ID of title to show for this item.
- * @param titleRes Optional resource ID of short title to show for this item.
+ * @param shortTitleRes Optional resource ID of short title to show for this item.
* @return Returns an Intent that can be launched to display the given
* fragment.
*/
@@ -1032,7 +1031,7 @@
* code in which to report the result.
* @param titleRes Resource ID of string to display for the title of
* this set of preferences.
- * @param titleRes Resource ID of string to display for the short title of
+ * @param shortTitleRes Resource ID of string to display for the short title of
* this set of preferences.
*/
public void startWithFragment(String fragmentName, Bundle args,
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 1a24716..b492615 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,7 +17,6 @@
package android.provider;
-import android.accounts.Account;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentProviderClient;
@@ -33,7 +32,6 @@
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.RemoteException;
-import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
@@ -93,20 +91,22 @@
/**
* Broadcast Action: This is the intent that gets fired when an alarm
* notification needs to be posted for a reminder.
+ *
+ * @SdkConstant
*/
- public static final String EVENT_REMINDER_ACTION = "android.intent.action.EVENT_REMINDER";
+ public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
/**
* Intent Extras key: The start time of an event or an instance of a
* recurring event. (milliseconds since epoch)
*/
- public static final String EVENT_BEGIN_TIME = "beginTime";
+ public static final String EXTRA_EVENT_BEGIN_TIME = "beginTime";
/**
* Intent Extras key: The end time of an event or an instance of a recurring
* event. (milliseconds since epoch)
*/
- public static final String EVENT_END_TIME = "endTime";
+ public static final String EXTRA_EVENT_END_TIME = "endTime";
/**
* This authority is used for writing to or querying from the calendar
@@ -118,8 +118,7 @@
/**
* The content:// style URL for the top-level calendar authority
*/
- public static final Uri CONTENT_URI =
- Uri.parse("content://" + AUTHORITY);
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
/**
* An optional insert, update or delete URI parameter that allows the caller
@@ -279,7 +278,7 @@
/**
* Columns specific to the Calendars Uri that other Uris can query.
*/
- protected interface CalendarsColumns {
+ protected interface CalendarColumns {
/**
* The color of the calendar
* <P>Type: INTEGER (color value)</P>
@@ -385,7 +384,7 @@
* Class that represents a Calendar Entity. There is one entry per calendar.
* This is a helper class to make batch operations easier.
*/
- public static class CalendarsEntity implements BaseColumns, SyncColumns, CalendarsColumns {
+ public static class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
/**
* The default Uri used when creating a new calendar EntityIterator.
@@ -476,63 +475,98 @@
}
/**
- * Fields and helpers for interacting with Calendars.
+ * Constants and helpers for the Calendars table, which contains details for
+ * individual calendars. <h3>Operations</h3> All operations can be done
+ * either as an app or as a sync adapter. To perform an operation as a sync
+ * adapter {@link #CALLER_IS_SYNCADAPTER} should be set to true and
+ * {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be set in the Uri
+ * parameters. See
+ * {@link Uri.Builder#appendQueryParameter(java.lang.String, java.lang.String)}
+ * for details on adding parameters. Sync adapters have write access to more
+ * columns but are restricted to a single account at a time. Calendars are
+ * designed to be primarily managed by a sync adapter and inserting new
+ * calendars should be done as a sync adapter. For the most part, apps
+ * should only update calendars (such as changing the color or display
+ * name). If a local calendar is required an app can do so by inserting as a
+ * sync adapter and using an {@link #ACCOUNT_TYPE} of
+ * {@link #ACCOUNT_TYPE_LOCAL} .
+ * <dl>
+ * <dt><b>Insert</b></dt>
+ * <dd>When inserting a new calendar the following fields must be included:
+ * <ul>
+ * <li>{@link #ACCOUNT_NAME}</li>
+ * <li>{@link #ACCOUNT_TYPE}</li>
+ * <li>{@link #NAME}</li>
+ * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+ * <li>{@link #CALENDAR_COLOR}</li>
+ * <li>{@link #CALENDAR_ACCESS_LEVEL}</li>
+ * <li>{@link #OWNER_ACCOUNT}</li>
+ * </ul>
+ * The following fields are not required when inserting a Calendar but are
+ * generally a good idea to include:
+ * <ul>
+ * <li>{@link #SYNC_EVENTS} set to 1</li>
+ * <li>{@link #CALENDAR_TIME_ZONE}</li>
+ * <li>{@link #ALLOWED_REMINDERS}</li>
+ * </ul>
+ * <dt><b>Update</b></dt>
+ * <dd>To perform an update on a calendar the {@link #_ID} of the calendar
+ * should be provided either as an appended id to the Uri (
+ * {@link ContentUris#withAppendedId}) or as the first selection item--the
+ * selection should start with "_id=?" and the first selectionArg should be
+ * the _id of the calendar. Calendars may also be updated using a selection
+ * without the id. In general, the {@link #ACCOUNT_NAME} and
+ * {@link #ACCOUNT_TYPE} should not be changed after a calendar is created
+ * as this can cause issues for sync adapters.
+ * <dt><b>Delete</b></dt>
+ * <dd>Calendars can be deleted either by the {@link #_ID} as an appended id
+ * on the Uri or using any standard selection. Deleting a calendar should
+ * generally be handled by a sync adapter as it will remove the calendar
+ * from the database and all associated data (aka events).</dd>
+ * <dt><b>Query</b></dt>
+ * <dd>Querying the Calendars table will get you all information about a set
+ * of calendars. There will be one row returned for each calendar that
+ * matches the query selection, or at most a single row if the {@link #_ID}
+ * is appended to the Uri.</dd>
+ * </dl>
+ * <h3>Calendar Columns</h3> The following Calendar columns are writable by
+ * both an app and a sync adapter.
+ * <ul>
+ * <li>{@link #NAME}</li>
+ * <li>{@link #CALENDAR_DISPLAY_NAME}</li>
+ * <li>{@link #CALENDAR_COLOR}</li>
+ * <li>{@link #VISIBLE}</li>
+ * <li>{@link #SYNC_EVENTS}</li>
+ * </ul>
+ * The following Calendars columns are writable only by a sync adapter
+ * <ul>
+ * <li>{@link #ACCOUNT_NAME}</li>
+ * <li>{@link #ACCOUNT_TYPE}</li>
+ * <li>{@link #_SYNC_ID}</li>
+ * <li>{@link #DIRTY}</li>
+ * <li>{@link #OWNER_ACCOUNT}</li>
+ * <li>{@link #MAX_REMINDERS}</li>
+ * <li>{@link #ALLOWED_REMINDERS}</li>
+ * <li>{@link #CAN_MODIFY_TIME_ZONE}</li>
+ * <li>{@link #CAN_ORGANIZER_RESPOND}</li>
+ * <li>{@link #CAN_PARTIALLY_UPDATE}</li>
+ * <li>{@link #CALENDAR_LOCATION}</li>
+ * <li>{@link #CALENDAR_TIME_ZONE}</li>
+ * <li>{@link #CALENDAR_ACCESS_LEVEL}</li>
+ * <li>{@link #DELETED}</li>
+ * <li>{@link #CAL_SYNC1}</li>
+ * <li>{@link #CAL_SYNC2}</li>
+ * <li>{@link #CAL_SYNC3}</li>
+ * <li>{@link #CAL_SYNC4}</li>
+ * <li>{@link #CAL_SYNC5}</li>
+ * <li>{@link #CAL_SYNC6}</li>
+ * <li>{@link #CAL_SYNC7}</li>
+ * <li>{@link #CAL_SYNC8}</li>
+ * <li>{@link #CAL_SYNC9}</li>
+ * <li>{@link #CAL_SYNC10}</li>
+ * </ul>
*/
- public static class Calendars implements BaseColumns, SyncColumns, CalendarsColumns {
- private static final String WHERE_DELETE_FOR_ACCOUNT = Calendars.ACCOUNT_NAME + "=?"
- + " AND "
- + Calendars.ACCOUNT_TYPE + "=?";
-
- /**
- * Helper function for generating a calendars query. This is blocking
- * and should not be used on the UI thread. See
- * {@link ContentResolver#query(Uri, String[], String, String[], String)}
- * for more details about using the parameters.
- *
- * @param cr The ContentResolver to query with
- * @param projection A list of columns to return
- * @param selection A formatted selection string
- * @param selectionArgs arguments to the selection string
- * @param orderBy How to order the returned rows
- * @return
- */
- public static final Cursor query(ContentResolver cr, String[] projection, String selection,
- String[] selectionArgs, String orderBy) {
- return cr.query(CONTENT_URI, projection, selection, selectionArgs,
- orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * Convenience method perform a delete on the Calendar provider. This is
- * a blocking call and should not be used on the UI thread.
- *
- * @param cr the ContentResolver
- * @param selection A filter to apply to rows before deleting, formatted
- * as an SQL WHERE clause (excluding the WHERE itself).
- * @param selectionArgs Fill in the '?'s in the selection
- * @return the count of rows that were deleted
- */
- public static int delete(ContentResolver cr, String selection, String[] selectionArgs)
- {
- return cr.delete(CONTENT_URI, selection, selectionArgs);
- }
-
- /**
- * Convenience method to delete all calendars that match the account.
- * This is a blocking call and should not be used on the UI thread.
- *
- * @param cr the ContentResolver
- * @param account the account whose calendars and events should be
- * deleted
- * @return the count of calendar rows that were deleted
- */
- public static int deleteCalendarsForAccount(ContentResolver cr, Account account) {
- // delete all calendars that match this account
- return CalendarContract.Calendars.delete(cr,
- WHERE_DELETE_FOR_ACCOUNT,
- new String[] { account.name, account.type });
- }
-
+ public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
/**
* The content:// style URL for accessing Calendars
*/
@@ -560,7 +594,9 @@
* These fields are only writable by a sync adapter. To modify them the
* caller must include {@link #CALLER_IS_SYNCADAPTER},
* {@link #ACCOUNT_NAME}, and {@link #ACCOUNT_TYPE} in the Uri's query
- * parameters.
+ * parameters. TODO move to provider
+ *
+ * @hide
*/
public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
ACCOUNT_NAME,
@@ -569,6 +605,7 @@
DIRTY,
OWNER_ACCOUNT,
MAX_REMINDERS,
+ ALLOWED_REMINDERS,
CAN_MODIFY_TIME_ZONE,
CAN_ORGANIZER_RESPOND,
CAN_PARTIALLY_UPDATE,
@@ -1252,13 +1289,15 @@
}
/**
- * Constants and helpers for the Events table, which contains details of a
- * single event. <h3>Operations</h3> All operations can be done either as an
- * app or as a sync adapter. To perform an operation as a sync adapter
- * {@link #CALLER_IS_SYNCADAPTER} should be set to true in the Uri
- * parameters and {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be
- * set. Sync adapters have write access to more columns but are restricted
- * to a single account at a time.
+ * Constants and helpers for the Events table, which contains details for
+ * individual events. <h3>Operations</h3> All operations can be done either
+ * as an app or as a sync adapter. To perform an operation as a sync adapter
+ * {@link #CALLER_IS_SYNCADAPTER} should be set to true and
+ * {@link #ACCOUNT_NAME} and {@link #ACCOUNT_TYPE} must be set in the Uri
+ * parameters. See
+ * {@link Uri.Builder#appendQueryParameter(java.lang.String, java.lang.String)}
+ * for details on adding parameters. Sync adapters have write access to more
+ * columns but are restricted to a single account at a time.
* <dl>
* <dt><b>Insert</b></dt>
* <dd>When inserting a new event the following fields must be included:
@@ -1270,13 +1309,14 @@
* There are also further requirements when inserting or updating an event.
* See the section on Writing to Events.</dd>
* <dt><b>Update</b></dt>
- * <dd>To perform an update on an Event the {@link Events#_ID} of the event
- * must be provided either as an appended id to the Uri (
+ * <dd>To perform an update of an Event the {@link Events#_ID} of the event
+ * should be provided either as an appended id to the Uri (
* {@link ContentUris#withAppendedId}) or as the first selection item--the
* selection should start with "_id=?" and the first selectionArg should be
- * the _id of the event. Updating an event must respect the same rules as
- * inserting and is further restricted in the fields that can be written.
- * See the section on Writing to Events.</dd>
+ * the _id of the event. Updates may also be done using a selection and no
+ * id. Updating an event must respect the same rules as inserting and is
+ * further restricted in the fields that can be written. See the section on
+ * Writing to Events.</dd>
* <dt><b>Delete</b></dt>
* <dd>Events can be deleted either by the {@link Events#_ID} as an appended
* id on the Uri or using any standard selection. If an appended id is used
@@ -1351,38 +1391,7 @@
* views into other tables and cannot be changed through the Events table.
*/
public static final class Events implements BaseColumns, SyncColumns, EventsColumns,
- CalendarsColumns {
-
- /**
- * Queries all events with the given projection. This is a blocking call
- * and should not be done on the UI thread.
- *
- * @param cr The content resolver to use for the query
- * @param projection The columns to return
- * @return A Cursor containing all events in the db
- */
- public static final Cursor query(ContentResolver cr, String[] projection) {
- return cr.query(CONTENT_URI, projection, null, null, DEFAULT_SORT_ORDER);
- }
-
- /**
- * Queries events using the given projection, selection filter, and
- * ordering. This is a blocking call and should not be done on the UI
- * thread. For selection and selectionArgs usage see
- * {@link ContentResolver#query(Uri, String[], String, String[], String)}
- *
- * @param cr The content resolver to use for the query
- * @param projection The columns to return
- * @param selection Filter on the query as an SQL WHERE statement
- * @param selectionArgs Args to replace any '?'s in the selection
- * @param orderBy How to order the rows as an SQL ORDER BY statement
- * @return A Cursor containing the matching events
- */
- public static final Cursor query(ContentResolver cr, String[] projection, String selection,
- String[] selectionArgs, String orderBy) {
- return cr.query(CONTENT_URI, projection, selection, null,
- orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
+ CalendarColumns {
/**
* The content:// style URL for interacting with events. Appending an
@@ -1398,7 +1407,7 @@
* appended event ID. Deletion of exceptions requires both the original event ID and
* the exception event ID (see {@link Uri.Builder#appendPath}).
*/
- public static final Uri EXCEPTION_CONTENT_URI =
+ public static final Uri CONTENT_EXCEPTION_URI =
Uri.parse("content://" + AUTHORITY + "/exception");
/**
@@ -1409,7 +1418,9 @@
/**
* These are columns that should only ever be updated by the provider,
* either because they are views mapped to another table or because they
- * are used for provider only functionality.
+ * are used for provider only functionality. TODO move to provider
+ *
+ * @hide
*/
public static String[] PROVIDER_WRITABLE_COLUMNS = new String[] {
ACCOUNT_NAME,
@@ -1439,7 +1450,9 @@
/**
* These fields are only writable by a sync adapter. To modify them the
* caller must include CALLER_IS_SYNCADAPTER, _SYNC_ACCOUNT, and
- * _SYNC_ACCOUNT_TYPE in the query parameters.
+ * _SYNC_ACCOUNT_TYPE in the query parameters. TODO move to provider.
+ *
+ * @hide
*/
public static final String[] SYNC_WRITABLE_COLUMNS = new String[] {
_SYNC_ID,
@@ -1463,9 +1476,12 @@
* days and minutes. The instances table is not writable and only provides a
* way to query event occurrences.
*/
- public static final class Instances implements BaseColumns, EventsColumns, CalendarsColumns {
+ public static final class Instances implements BaseColumns, EventsColumns, CalendarColumns {
- private static final String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=1";
+ private static final String WHERE_CALENDARS_SELECTED = Calendars.VISIBLE + "=?";
+ private static final String[] WHERE_CALENDARS_ARGS = {
+ "1"
+ };
/**
* Performs a query to return all visible instances in the given range.
@@ -1488,7 +1504,7 @@
ContentUris.appendId(builder, begin);
ContentUris.appendId(builder, end);
return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED,
- null, DEFAULT_SORT_ORDER);
+ WHERE_CALENDARS_ARGS, DEFAULT_SORT_ORDER);
}
/**
@@ -1517,79 +1533,8 @@
ContentUris.appendId(builder, begin);
ContentUris.appendId(builder, end);
builder = builder.appendPath(searchQuery);
- return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED, null,
- DEFAULT_SORT_ORDER);
- }
-
- /**
- * Performs a query to return all visible instances in the given range
- * that match the given selection. This is a blocking function and
- * should not be done on the UI thread. This will cause an expansion of
- * recurring events to fill this time range if they are not already
- * expanded and will slow down for larger time ranges with many
- * recurring events.
- *
- * @param cr The ContentResolver to use for the query
- * @param projection The columns to return
- * @param begin The start of the time range to query in UTC millis since
- * epoch
- * @param end The end of the time range to query in UTC millis since
- * epoch
- * @param selection Filter on the query as an SQL WHERE statement
- * @param selectionArgs Args to replace any '?'s in the selection
- * @param orderBy How to order the rows as an SQL ORDER BY statement
- * @return A Cursor of instances matching the selection
- */
- public static final Cursor query(ContentResolver cr, String[] projection, long begin,
- long end, String selection, String[] selectionArgs, String orderBy) {
- Uri.Builder builder = CONTENT_URI.buildUpon();
- ContentUris.appendId(builder, begin);
- ContentUris.appendId(builder, end);
- if (TextUtils.isEmpty(selection)) {
- selection = WHERE_CALENDARS_SELECTED;
- } else {
- selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
- }
- return cr.query(builder.build(), projection, selection, selectionArgs,
- orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
- }
-
- /**
- * Performs a query to return all visible instances in the given range
- * that match the given selection. This is a blocking function and
- * should not be done on the UI thread. This will cause an expansion of
- * recurring events to fill this time range if they are not already
- * expanded and will slow down for larger time ranges with many
- * recurring events.
- *
- * @param cr The ContentResolver to use for the query
- * @param projection The columns to return
- * @param begin The start of the time range to query in UTC millis since
- * epoch
- * @param end The end of the time range to query in UTC millis since
- * epoch
- * @param searchQuery A string of space separated search terms. Segments
- * enclosed by double quotes will be treated as a single
- * term.
- * @param selection Filter on the query as an SQL WHERE statement
- * @param selectionArgs Args to replace any '?'s in the selection
- * @param orderBy How to order the rows as an SQL ORDER BY statement
- * @return A Cursor of instances matching the selection
- */
- public static final Cursor query(ContentResolver cr, String[] projection, long begin,
- long end, String searchQuery, String selection, String[] selectionArgs,
- String orderBy) {
- Uri.Builder builder = CONTENT_SEARCH_URI.buildUpon();
- ContentUris.appendId(builder, begin);
- ContentUris.appendId(builder, end);
- builder = builder.appendPath(searchQuery);
- if (TextUtils.isEmpty(selection)) {
- selection = WHERE_CALENDARS_SELECTED;
- } else {
- selection = "(" + selection + ") AND " + WHERE_CALENDARS_SELECTED;
- }
- return cr.query(builder.build(), projection, selection, selectionArgs,
- orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
+ return cr.query(builder.build(), projection, WHERE_CALENDARS_SELECTED,
+ WHERE_CALENDARS_ARGS, DEFAULT_SORT_ORDER);
}
/**
@@ -1674,11 +1619,6 @@
public static final String END_MINUTE = "endMinute";
}
- /**
- * CalendarCache stores some settings for calendar including the current
- * time zone for the instaces. These settings are stored using a key/value
- * scheme.
- */
protected interface CalendarCacheColumns {
/**
* The key for the setting. Keys are defined in {@link CalendarCache}.
@@ -1691,31 +1631,24 @@
public static final String VALUE = "value";
}
+ /**
+ * CalendarCache stores some settings for calendar including the current
+ * time zone for the instances. These settings are stored using a key/value
+ * scheme. A {@link #KEY} must be specified when updating these values.
+ */
public static class CalendarCache implements CalendarCacheColumns {
/**
* The URI to use for retrieving the properties from the Calendar db.
*/
public static final Uri URI =
Uri.parse("content://" + AUTHORITY + "/properties");
- public static final String[] POJECTION = { KEY, VALUE };
-
- /**
- * If updating a property, this must be provided as the selection. All
- * other selections will fail. For queries this field can be omitted to
- * retrieve all properties or used to query a single property. Valid
- * keys include {@link #TIMEZONE_KEY_TYPE},
- * {@link #TIMEZONE_KEY_INSTANCES}, and
- * {@link #TIMEZONE_KEY_INSTANCES_PREVIOUS}, though the last one can
- * only be read, not written.
- */
- public static final String WHERE = "key=?";
/**
* They key for updating the use of auto/home time zones in Calendar.
* Valid values are {@link #TIMEZONE_TYPE_AUTO} or
* {@link #TIMEZONE_TYPE_HOME}.
*/
- public static final String TIMEZONE_KEY_TYPE = "timezoneType";
+ public static final String KEY_TIMEZONE_TYPE = "timezoneType";
/**
* The key for updating the time zone used by the provider when it
@@ -1723,24 +1656,24 @@
* type is set to {@link #TIMEZONE_TYPE_HOME}. A valid time zone id
* should be written to this field.
*/
- public static final String TIMEZONE_KEY_INSTANCES = "timezoneInstances";
+ public static final String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
/**
* The key for reading the last time zone set by the user. This should
* only be read by apps and it will be automatically updated whenever
- * {@link #TIMEZONE_KEY_INSTANCES} is updated with
+ * {@link #KEY_TIMEZONE_INSTANCES} is updated with
* {@link #TIMEZONE_TYPE_HOME} set.
*/
- public static final String TIMEZONE_KEY_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+ public static final String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
/**
- * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+ * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
* should stay in sync with the device's time zone.
*/
public static final String TIMEZONE_TYPE_AUTO = "auto";
/**
- * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+ * The value to write to {@link #KEY_TIMEZONE_TYPE} if the provider
* should use a fixed time zone set by the user.
*/
public static final String TIMEZONE_TYPE_HOME = "home";
@@ -1748,8 +1681,10 @@
/**
* A few Calendar globals are needed in the CalendarProvider for expanding
- * the Instances table and these are all stored in the first (and only)
- * row of the CalendarMetaData table.
+ * the Instances table and these are all stored in the first (and only) row
+ * of the CalendarMetaData table.
+ *
+ * @hide
*/
protected interface CalendarMetaDataColumns {
/**
@@ -1815,7 +1750,9 @@
/**
* The projection used by the EventDays query.
*/
- public static final String[] PROJECTION = { STARTDAY, ENDDAY };
+ public static final String[] PROJECTION = {
+ STARTDAY, ENDDAY
+ };
private static final String SELECTION = "selected=1";
/**
@@ -1966,17 +1903,28 @@
public static final String NOTIFY_TIME = "notifyTime";
/**
- * The state of this alert. It starts out as {@link #SCHEDULED}, then
- * when the alarm goes off, it changes to {@link #FIRED}, and then when
- * the user dismisses the alarm it changes to {@link #DISMISSED}. Column
+ * The state of this alert. It starts out as {@link #STATE_SCHEDULED}, then
+ * when the alarm goes off, it changes to {@link #STATE_FIRED}, and then when
+ * the user dismisses the alarm it changes to {@link #STATE_DISMISSED}. Column
* name.
* <P>Type: INTEGER</P>
*/
public static final String STATE = "state";
- public static final int SCHEDULED = 0;
- public static final int FIRED = 1;
- public static final int DISMISSED = 2;
+ /**
+ * An alert begins in this state when it is first created.
+ */
+ public static final int STATE_SCHEDULED = 0;
+ /**
+ * After a notification for an alert has been created it should be
+ * updated to fired.
+ */
+ public static final int STATE_FIRED = 1;
+ /**
+ * Once the user has dismissed the notification the alert's state should
+ * be set to dismissed so it is not fired again.
+ */
+ public static final int STATE_DISMISSED = 2;
/**
* The number of minutes that this alarm precedes the start time. Column
@@ -1994,7 +1942,7 @@
/**
* Fields and helpers for accessing calendar alerts information. These
* fields are for tracking which alerts have been fired. Scheduled alarms
- * will generate an intent using {@link #EVENT_REMINDER_ACTION}. Apps that
+ * will generate an intent using {@link #ACTION_EVENT_REMINDER}. Apps that
* receive this action may update the {@link #STATE} for the reminder when
* they have finished handling it. Apps that have their notifications
* disabled should not modify the table to ensure that they do not conflict
@@ -2003,7 +1951,7 @@
* state of a reminder.
*/
public static final class CalendarAlerts implements BaseColumns,
- CalendarAlertsColumns, EventsColumns, CalendarsColumns {
+ CalendarAlertsColumns, EventsColumns, CalendarColumns {
/**
* @hide
@@ -2023,7 +1971,7 @@
private static final String WHERE_FINDNEXTALARMTIME = ALARM_TIME + ">=?";
private static final String SORT_ORDER_ALARMTIME_ASC = ALARM_TIME + " ASC";
- private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + SCHEDULED
+ private static final String WHERE_RESCHEDULE_MISSED_ALARMS = STATE + "=" + STATE_SCHEDULED
+ " AND " + ALARM_TIME + "<?"
+ " AND " + ALARM_TIME + ">?"
+ " AND " + END + ">=?";
@@ -2037,10 +1985,11 @@
public static final Uri CONTENT_URI_BY_INSTANCE =
Uri.parse("content://" + AUTHORITY + "/calendar_alerts/by_instance");
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
/**
- * Helper for inserting an alarm time associated with an event
+ * Helper for inserting an alarm time associated with an event TODO move
+ * to Provider
*
* @hide
*/
@@ -2055,51 +2004,32 @@
values.put(CalendarAlerts.CREATION_TIME, currentTime);
values.put(CalendarAlerts.RECEIVED_TIME, 0);
values.put(CalendarAlerts.NOTIFY_TIME, 0);
- values.put(CalendarAlerts.STATE, SCHEDULED);
+ values.put(CalendarAlerts.STATE, STATE_SCHEDULED);
values.put(CalendarAlerts.MINUTES, minutes);
return cr.insert(CONTENT_URI, values);
}
/**
- * Queries alerts info using the given projection, selection filter, and
- * ordering. This is a blocking call and should not be done on the UI
- * thread. For selection and selectionArgs usage see
- * {@link ContentResolver#query(Uri, String[], String, String[], String)}
- *
- * @param cr The content resolver to use for the query
- * @param projection The columns to return
- * @param selection Filter on the query as an SQL WHERE statement
- * @param selectionArgs Args to replace any '?'s in the selection
- * @param sortOrder How to order the rows as an SQL ORDER BY statement
- * @return A Cursor containing the matching alerts
- */
- public static final Cursor query(ContentResolver cr, String[] projection,
- String selection, String[] selectionArgs, String sortOrder) {
- return cr.query(CONTENT_URI, projection, selection, selectionArgs,
- sortOrder);
- }
-
- /**
* Finds the next alarm after (or equal to) the given time and returns
* the time of that alarm or -1 if no such alarm exists. This is a
- * blocking call and should not be done on the UI thread.
+ * blocking call and should not be done on the UI thread. TODO move to
+ * provider
*
* @param cr the ContentResolver
* @param millis the time in UTC milliseconds
* @return the next alarm time greater than or equal to "millis", or -1
* if no such alarm exists.
+ * @hide
*/
public static final long findNextAlarmTime(ContentResolver cr, long millis) {
String selection = ALARM_TIME + ">=" + millis;
// TODO: construct an explicit SQL query so that we can add
// "LIMIT 1" to the end and get just one result.
String[] projection = new String[] { ALARM_TIME };
- Cursor cursor = query(cr, projection,
- WHERE_FINDNEXTALARMTIME,
- new String[] {
+ Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_FINDNEXTALARMTIME,
+ (new String[] {
Long.toString(millis)
- },
- SORT_ORDER_ALARMTIME_ASC);
+ }), SORT_ORDER_ALARMTIME_ASC);
long alarmTime = -1;
try {
if (cursor != null && cursor.moveToFirst()) {
@@ -2115,13 +2045,14 @@
/**
* Searches the CalendarAlerts table for alarms that should have fired
- * but have not and then reschedules them. This method can be called
- * at boot time to restore alarms that may have been lost due to a
- * phone reboot.
+ * but have not and then reschedules them. This method can be called at
+ * boot time to restore alarms that may have been lost due to a phone
+ * reboot. TODO move to provider
*
* @param cr the ContentResolver
* @param context the Context
* @param manager the AlarmManager
+ * @hide
*/
public static final void rescheduleMissedAlarms(ContentResolver cr,
Context context, AlarmManager manager) {
@@ -2135,15 +2066,10 @@
// TODO: construct an explicit SQL query so that we can add
// "GROUPBY" instead of doing a sort and de-dup
- Cursor cursor = CalendarAlerts.query(cr,
- projection,
- WHERE_RESCHEDULE_MISSED_ALARMS,
- new String[] {
- Long.toString(now),
- Long.toString(ancient),
- Long.toString(now)
- },
- SORT_ORDER_ALARMTIME_ASC);
+ Cursor cursor = cr.query(CalendarAlerts.CONTENT_URI, projection,
+ WHERE_RESCHEDULE_MISSED_ALARMS, (new String[] {
+ Long.toString(now), Long.toString(ancient), Long.toString(now)
+ }), SORT_ORDER_ALARMTIME_ASC);
if (cursor == null) {
return;
}
@@ -2176,12 +2102,13 @@
* keep scheduled reminders up to date but apps may use this to
* implement snooze functionality without modifying the reminders table.
* Scheduled alarms will generate an intent using
- * {@link #EVENT_REMINDER_ACTION}.
+ * {@link #ACTION_EVENT_REMINDER}. TODO Move to provider
*
* @param context A context for referencing system resources
* @param manager The AlarmManager to use or null
* @param alarmTime The time to fire the intent in UTC millis since
* epoch
+ * @hide
*/
public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
if (DEBUG) {
@@ -2195,7 +2122,7 @@
manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
- Intent intent = new Intent(EVENT_REMINDER_ACTION);
+ Intent intent = new Intent(ACTION_EVENT_REMINDER);
intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime));
intent.putExtra(ALARM_TIME, alarmTime);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
@@ -2203,31 +2130,28 @@
}
/**
- * Searches for an entry in the CalendarAlerts table that matches
- * the given event id, begin time and alarm time. If one is found
- * then this alarm already exists and this method returns true.
- *
+ * Searches for an entry in the CalendarAlerts table that matches the
+ * given event id, begin time and alarm time. If one is found then this
+ * alarm already exists and this method returns true. TODO Move to
+ * provider
+ *
* @param cr the ContentResolver
* @param eventId the event id to match
* @param begin the start time of the event in UTC millis
* @param alarmTime the alarm time of the event in UTC millis
- * @return true if there is already an alarm for the given event
- * with the same start time and alarm time.
+ * @return true if there is already an alarm for the given event with
+ * the same start time and alarm time.
+ * @hide
*/
public static final boolean alarmExists(ContentResolver cr, long eventId,
long begin, long alarmTime) {
// TODO: construct an explicit SQL query so that we can add
// "LIMIT 1" to the end and get just one result.
String[] projection = new String[] { ALARM_TIME };
- Cursor cursor = query(cr,
- projection,
- WHERE_ALARM_EXISTS,
- new String[] {
- Long.toString(eventId),
- Long.toString(begin),
- Long.toString(alarmTime)
- },
- null);
+ Cursor cursor = cr.query(CONTENT_URI, projection, WHERE_ALARM_EXISTS,
+ (new String[] {
+ Long.toString(eventId), Long.toString(begin), Long.toString(alarmTime)
+ }), null);
boolean found = false;
try {
if (cursor != null && cursor.getCount() > 0) {
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 02faf49..39c6f57 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.DataUsageFeedback;
import android.text.TextUtils;
/**
@@ -55,6 +57,29 @@
Uri.parse("content://call_log/calls/filter");
/**
+ * An optional URI parameter which instructs the provider to allow the operation to be
+ * applied to voicemail records as well.
+ * <p>
+ * TYPE: Boolean
+ * <p>
+ * Using this parameter with a value of {@code true} will result in a security error if the
+ * calling package does not have appropriate permissions to access voicemails.
+ *
+ * @hide
+ */
+ public static final String ALLOW_VOICEMAILS_PARAM_KEY = "allow_voicemails";
+
+ /**
+ * Content uri with {@link #ALLOW_VOICEMAILS_PARAM_KEY} set. This can directly be used to
+ * access call log entries that includes voicemail records.
+ *
+ * @hide
+ */
+ public static final Uri CONTENT_URI_WITH_VOICEMAIL = CONTENT_URI.buildUpon()
+ .appendQueryParameter(ALLOW_VOICEMAILS_PARAM_KEY, "true")
+ .build();
+
+ /**
* The default sort order for this table
*/
public static final String DEFAULT_SORT_ORDER = "date DESC";
@@ -204,7 +229,44 @@
}
if ((ci != null) && (ci.person_id > 0)) {
- ContactsContract.Contacts.markAsContacted(resolver, ci.person_id);
+ // Update usage information for the number associated with the contact ID.
+ // We need to use both the number and the ID for obtaining a data ID since other
+ // contacts may have the same number.
+
+ final Cursor cursor;
+
+ // We should prefer normalized one (probably coming from
+ // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
+ if (ci.normalizedNumber != null) {
+ final String normalizedPhoneNumber = ci.normalizedNumber;
+ cursor = resolver.query(Phone.CONTENT_URI,
+ new String[] { Phone._ID },
+ Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
+ new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
+ null);
+ } else {
+ final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
+ cursor = resolver.query(Phone.CONTENT_URI,
+ new String[] { Phone._ID },
+ Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
+ new String[] { String.valueOf(ci.person_id), phoneNumber},
+ null);
+ }
+
+ if (cursor != null) {
+ try {
+ if (cursor.getCount() > 0 && cursor.moveToFirst()) {
+ final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
+ .appendPath(cursor.getString(0))
+ .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+ DataUsageFeedback.USAGE_TYPE_CALL)
+ .build();
+ resolver.update(feedbackUri, new ContentValues(), null, null);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
}
Uri result = resolver.insert(CONTENT_URI, values);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 1816066..ad71061 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -123,14 +123,16 @@
/**
* An optional URI parameter for selection queries that instructs the
- * provider to include the user's personal profile contact entry (if any)
- * in the contact results. If present, the user's profile will always be
- * the first entry returned. The default value is false.
+ * provider to allow the user's personal profile contact entry (if any)
+ * to appear in a list of contact results. It is only useful when issuing
+ * a query that may retrieve more than one contact. If present, the user's
+ * profile will always be the first entry returned. The default value is
+ * false.
*
* Specifying this parameter will result in a security error if the calling
* application does not have android.permission.READ_PROFILE permission.
*/
- public static final String INCLUDE_PROFILE = "include_profile";
+ public static final String ALLOW_PROFILE = "allow_profile";
/**
* A query parameter key used to specify the package that is requesting a query.
@@ -163,17 +165,24 @@
* obtaining possible recipients, letting the provider know which account is selected during
* the composition. The provider may use the "primary account" information to optimize
* the search result.
- * @hide
*/
public static final String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
/**
* A query parameter specifing a primary account. This parameter should be used with
* {@link #PRIMARY_ACCOUNT_NAME}. See the doc in {@link #PRIMARY_ACCOUNT_NAME}.
- * @hide
*/
public static final String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
+ /**
+ * A boolean parameter for {@link Contacts#CONTENT_STREQUENT_URI} and
+ * {@link Contacts#CONTENT_STREQUENT_FILTER_URI}, which requires the ContactsProvider to
+ * return only phone-related results. For example, frequently contacted person list should
+ * include persons contacted via phone (not email, sms, etc.)
+ *
+ * @hide
+ */
+ public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
/**
* @hide
@@ -6317,7 +6326,6 @@
* boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0;
* </pre>
* </p>
- * @hide
*/
public static final class DataUsageFeedback {
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 0a8c3ca..ba4804d 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -548,14 +548,6 @@
}
/**
- * This download has been paused because requesting application has been
- * blocked by {@link NetworkPolicyManager}.
- *
- * @hide
- */
- public static final int STATUS_PAUSED_BY_POLICY = 189;
-
- /**
* This download hasn't stated yet
*/
public static final int STATUS_PENDING = 190;
@@ -704,6 +696,14 @@
public static final int STATUS_TOO_MANY_REDIRECTS = 497;
/**
+ * This download has failed because requesting application has been
+ * blocked by {@link NetworkPolicyManager}.
+ *
+ * @hide
+ */
+ public static final int STATUS_BLOCKED = 498;
+
+ /**
* This download is visible but only shows in the notifications
* while it's in progress.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 01e028e7..65babc2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -20,6 +20,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.SearchManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -300,6 +301,21 @@
"android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
/**
+ * Activity Action: Show a dialog to select input method.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_INPUT_METHOD_PICKER =
+ "android.settings.SHOW_INPUT_METHOD_PICKER";
+
+ /**
* Activity Action: Show settings to manage the user input dictionary.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -3475,6 +3491,18 @@
"sms_outgoing_check_max_count";
/**
+ * The global search provider chosen by the user (if multiple global
+ * search providers are installed). This will be the provider returned
+ * by {@link SearchManager#getGlobalSearchActivity()} if it's still
+ * installed. This setting is stored as a flattened component name as
+ * per {@link ComponentName#flattenToString()}.
+ *
+ * @hide
+ */
+ public static final String SEARCH_GLOBAL_SEARCH_ACTIVITY =
+ "search_global_search_activity";
+
+ /**
* The number of promoted sources in GlobalSearch.
* @hide
*/
@@ -3789,6 +3817,8 @@
"dream_timeout";
/** {@hide} */
+ public static final String NETSTATS_ENABLED = "netstats_enabled";
+ /** {@hide} */
public static final String NETSTATS_POLL_INTERVAL = "netstats_poll_interval";
/** {@hide} */
public static final String NETSTATS_PERSIST_THRESHOLD = "netstats_persist_threshold";
@@ -3800,6 +3830,8 @@
public static final String NETSTATS_UID_BUCKET_DURATION = "netstats_uid_bucket_duration";
/** {@hide} */
public static final String NETSTATS_UID_MAX_HISTORY = "netstats_uid_max_history";
+ /** {@hide} */
+ public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history";
/**
* @hide
diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java
index 2fcf315..027aed1 100644
--- a/core/java/android/provider/SyncConstValue.java
+++ b/core/java/android/provider/SyncConstValue.java
@@ -18,7 +18,7 @@
/**
* Columns for tables that are synced to a server.
- * @deprecated
+ * @deprecated Do not use.
* @hide
*/
public interface SyncConstValue
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index ae41876..ab0cb50 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -63,14 +63,13 @@
// TODO: Move ACTION_NEW_VOICEMAIL to the Intent class.
/** Broadcast intent when a new voicemail record is inserted. */
public static final String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+
/**
* Extra included in {@value Intent#ACTION_PROVIDER_CHANGED} and
- * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate the package
- * that caused the change in content provider.
- * <p>Receivers of the broadcast can use this field to determine if this is
- * a self change.
+ * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate if the receiving
+ * package made this change.
*/
- public static final String EXTRA_CHANGED_BY = "com.android.voicemail.extra.CHANGED_BY";
+ public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
/** The mime type for a collection of voicemails. */
public static final String DIR_TYPE =
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
index a36cd24..76e7885 100644
--- a/core/java/android/server/BluetoothBondState.java
+++ b/core/java/android/server/BluetoothBondState.java
@@ -89,7 +89,12 @@
return mPendingOutgoingBonding;
}
- public synchronized void loadBondState() {
+ public synchronized void initBondState() {
+ getProfileProxy();
+ loadBondState();
+ }
+
+ private void loadBondState() {
if (mService.getBluetoothStateInternal() !=
BluetoothAdapter.STATE_TURNING_ON) {
return;
@@ -131,10 +136,6 @@
if (state == BluetoothDevice.BOND_BONDED) {
mService.addProfileState(address);
- } else if (state == BluetoothDevice.BOND_BONDING) {
- if (mA2dpProxy == null || mHeadsetProxy == null) {
- getProfileProxy();
- }
} else if (state == BluetoothDevice.BOND_NONE) {
mService.removeProfileState(address);
}
diff --git a/core/java/android/server/BluetoothDeviceProperties.java b/core/java/android/server/BluetoothDeviceProperties.java
index 3dc53d7..fe3ef79 100644
--- a/core/java/android/server/BluetoothDeviceProperties.java
+++ b/core/java/android/server/BluetoothDeviceProperties.java
@@ -35,43 +35,45 @@
mService = service;
}
- synchronized Map<String, String> addProperties(String address,
- String[] properties) {
+ Map<String, String> addProperties(String address, String[] properties) {
/*
* We get a DeviceFound signal every time RSSI changes or name changes.
* Don't create a new Map object every time.
*/
- Map<String, String> propertyValues = mPropertiesMap.get(address);
- if (propertyValues == null) {
- propertyValues = new HashMap<String, String>();
- }
+ Map<String, String> propertyValues;
+ synchronized(mPropertiesMap) {
+ propertyValues = mPropertiesMap.get(address);
+ if (propertyValues == null) {
+ propertyValues = new HashMap<String, String>();
+ }
- for (int i = 0; i < properties.length; i++) {
- String name = properties[i];
- String newValue = null;
- int len;
- if (name == null) {
- Log.e(TAG, "Error: Remote Device Property at index "
+ for (int i = 0; i < properties.length; i++) {
+ String name = properties[i];
+ String newValue = null;
+ int len;
+ if (name == null) {
+ Log.e(TAG, "Error: Remote Device Property at index "
+ i + " is null");
- continue;
- }
- if (name.equals("UUIDs") || name.equals("Nodes")) {
- StringBuilder str = new StringBuilder();
- len = Integer.valueOf(properties[++i]);
- for (int j = 0; j < len; j++) {
- str.append(properties[++i]);
- str.append(",");
+ continue;
}
- if (len > 0) {
- newValue = str.toString();
+ if (name.equals("UUIDs") || name.equals("Nodes")) {
+ StringBuilder str = new StringBuilder();
+ len = Integer.valueOf(properties[++i]);
+ for (int j = 0; j < len; j++) {
+ str.append(properties[++i]);
+ str.append(",");
+ }
+ if (len > 0) {
+ newValue = str.toString();
+ }
+ } else {
+ newValue = properties[++i];
}
- } else {
- newValue = properties[++i];
- }
- propertyValues.put(name, newValue);
+ propertyValues.put(name, newValue);
+ }
+ mPropertiesMap.put(address, propertyValues);
}
- mPropertiesMap.put(address, propertyValues);
// We have added a new remote device or updated its properties.
// Also update the serviceChannel cache.
@@ -79,46 +81,56 @@
return propertyValues;
}
- synchronized void setProperty(String address, String name, String value) {
- Map <String, String> propVal = mPropertiesMap.get(address);
- if (propVal != null) {
- propVal.put(name, value);
- mPropertiesMap.put(address, propVal);
- } else {
- Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
+ void setProperty(String address, String name, String value) {
+ synchronized(mPropertiesMap) {
+ Map <String, String> propVal = mPropertiesMap.get(address);
+ if (propVal != null) {
+ propVal.put(name, value);
+ mPropertiesMap.put(address, propVal);
+ } else {
+ Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
+ }
}
}
- synchronized boolean isInCache(String address) {
- return (mPropertiesMap.get(address) != null);
+ boolean isInCache(String address) {
+ synchronized (mPropertiesMap) {
+ return (mPropertiesMap.get(address) != null);
+ }
}
- synchronized boolean isEmpty() {
- return mPropertiesMap.isEmpty();
+ boolean isEmpty() {
+ synchronized (mPropertiesMap) {
+ return mPropertiesMap.isEmpty();
+ }
}
- synchronized Set<String> keySet() {
- return mPropertiesMap.keySet();
+ Set<String> keySet() {
+ synchronized (mPropertiesMap) {
+ return mPropertiesMap.keySet();
+ }
}
- synchronized String getProperty(String address, String property) {
- Map<String, String> properties = mPropertiesMap.get(address);
- if (properties != null) {
- return properties.get(property);
- } else {
- // Query for remote device properties, again.
- // We will need to reload the cache when we switch Bluetooth on / off
- // or if we crash.
- properties = updateCache(address);
+ String getProperty(String address, String property) {
+ synchronized(mPropertiesMap) {
+ Map<String, String> properties = mPropertiesMap.get(address);
if (properties != null) {
return properties.get(property);
+ } else {
+ // Query for remote device properties, again.
+ // We will need to reload the cache when we switch Bluetooth on / off
+ // or if we crash.
+ properties = updateCache(address);
+ if (properties != null) {
+ return properties.get(property);
+ }
}
}
Log.e(TAG, "getRemoteDeviceProperty: " + property + " not present: " + address);
return null;
}
- synchronized Map<String, String> updateCache(String address) {
+ Map<String, String> updateCache(String address) {
String[] propValues = mService.getRemoteDeviceProperties(address);
if (propValues != null) {
return addProperties(address, propValues);
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index e72aaa7..a220007 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -989,6 +989,33 @@
BluetoothPan.LOCAL_NAP_ROLE);
}
+ /**
+ * Called by native code on a PropertyChanged signal from
+ * org.bluez.HealthDevice.
+ *
+ * @param devicePath the object path of the remote device
+ * @param propValues Properties (Name-Value) of the Health Device.
+ */
+ private void onHealthDevicePropertyChanged(String devicePath, String[] propValues) {
+ log("Health Device : Name of Property is: " + propValues[0] + " Value:" + propValues[1]);
+ mBluetoothService.onHealthDevicePropertyChanged(devicePath, propValues[1]);
+ }
+
+ /**
+ * Called by native code on a ChannelCreated/Deleted signal from
+ * org.bluez.HealthDevice.
+ *
+ * @param devicePath the object path of the remote device
+ * @param channelPath the path of the health channel.
+ * @param exists Boolean to indicate if the channel was created or deleted.
+ */
+ private void onHealthDeviceChannelChanged(String devicePath, String channelPath,
+ boolean exists) {
+ log("Health Device : devicePath: " + devicePath + ":channelPath:" + channelPath +
+ ":exists" + exists);
+ mBluetoothService.onHealthDeviceChannelChanged(devicePath, channelPath, exists);
+ }
+
private void onRestartRequired() {
if (mBluetoothService.isEnabled()) {
Log.e(TAG, "*** A serious error occurred (did bluetoothd crash?) - " +
diff --git a/core/java/android/server/BluetoothHealthProfileHandler.java b/core/java/android/server/BluetoothHealthProfileHandler.java
new file mode 100644
index 0000000..7f862e0
--- /dev/null
+++ b/core/java/android/server/BluetoothHealthProfileHandler.java
@@ -0,0 +1,600 @@
+/*
+ * 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 android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHealth;
+import android.bluetooth.BluetoothHealthAppConfiguration;
+import android.bluetooth.BluetoothHealth;
+import android.bluetooth.BluetoothInputDevice;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * This handles all the operations on the Bluetooth Health profile.
+ * All functions are called by BluetoothService, as Bluetooth Service
+ * is the Service handler for the HDP profile.
+ *
+ * @hide
+ */
+final class BluetoothHealthProfileHandler {
+ private static final String TAG = "BluetoothHealthProfileHandler";
+ /*STOPSHIP*/
+ private static final boolean DBG = true;
+
+ private static BluetoothHealthProfileHandler sInstance;
+ private Context mContext;
+ private BluetoothService mBluetoothService;
+ private ArrayList<HealthChannel> mHealthChannels;
+ private HashMap <BluetoothHealthAppConfiguration, String> mHealthAppConfigs;
+ private HashMap <BluetoothDevice, Integer> mHealthDevices;
+
+ private static final int MESSAGE_REGISTER_APPLICATION = 0;
+ private static final int MESSAGE_UNREGISTER_APPLICATION = 1;
+ private static final int MESSAGE_CONNECT_CHANNEL = 2;
+
+ class HealthChannel {
+ private ParcelFileDescriptor mChannelFd;
+ private boolean mMainChannel;
+ private String mChannelPath;
+ private BluetoothDevice mDevice;
+ private BluetoothHealthAppConfiguration mConfig;
+ private int mState;
+ private int mChannelType;
+
+ HealthChannel(BluetoothDevice device, BluetoothHealthAppConfiguration config,
+ ParcelFileDescriptor fd, boolean mainChannel, String channelPath) {
+ mChannelFd = fd;
+ mMainChannel = mainChannel;
+ mChannelPath = channelPath;
+ mDevice = device;
+ mConfig = config;
+ mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ }
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_REGISTER_APPLICATION:
+ BluetoothHealthAppConfiguration registerApp =
+ (BluetoothHealthAppConfiguration) msg.obj;
+ int role = registerApp.getRole();
+ String path = null;
+
+ if (role == BluetoothHealth.SINK_ROLE) {
+ path = mBluetoothService.registerHealthApplicationNative(
+ registerApp.getDataType(), getStringRole(role), registerApp.getName());
+ } else {
+ path = mBluetoothService.registerHealthApplicationNative(
+ registerApp.getDataType(), getStringRole(role), registerApp.getName(),
+ getStringChannelType(registerApp.getChannelType()));
+ }
+
+ if (path == null) {
+ callHealthApplicationStatusCallback(registerApp,
+ BluetoothHealth.APPLICATION_REGISTRATION_FAILURE);
+ } else {
+ mHealthAppConfigs.put(registerApp, path);
+ callHealthApplicationStatusCallback(registerApp,
+ BluetoothHealth.APPLICATION_REGISTRATION_SUCCESS);
+ }
+
+ break;
+ case MESSAGE_UNREGISTER_APPLICATION:
+ BluetoothHealthAppConfiguration unregisterApp =
+ (BluetoothHealthAppConfiguration) msg.obj;
+ boolean result = mBluetoothService.unregisterHealthApplicationNative(
+ mHealthAppConfigs.get(unregisterApp));
+ if (result) {
+ callHealthApplicationStatusCallback(unregisterApp,
+ BluetoothHealth.APPLICATION_UNREGISTRATION_SUCCESS);
+ } else {
+ callHealthApplicationStatusCallback(unregisterApp,
+ BluetoothHealth.APPLICATION_UNREGISTRATION_FAILURE);
+ }
+ break;
+ case MESSAGE_CONNECT_CHANNEL:
+ HealthChannel chan = (HealthChannel)msg.obj;
+ String deviceObjectPath =
+ mBluetoothService.getObjectPathFromAddress(chan.mDevice.getAddress());
+ String configPath = mHealthAppConfigs.get(chan.mConfig);
+ String channelType = getStringChannelType(chan.mChannelType);
+
+ if (!mBluetoothService.createChannelNative(deviceObjectPath, configPath,
+ channelType)) {
+ int prevState = chan.mState;
+ int state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ callHealthChannelCallback(chan.mConfig, chan.mDevice, prevState, state, null);
+ mHealthChannels.remove(chan);
+ }
+ }
+ }
+ };
+
+ private BluetoothHealthProfileHandler(Context context, BluetoothService service) {
+ mContext = context;
+ mBluetoothService = service;
+ mHealthAppConfigs = new HashMap<BluetoothHealthAppConfiguration, String>();
+ mHealthChannels = new ArrayList<HealthChannel>();
+ mHealthDevices = new HashMap<BluetoothDevice, Integer>();
+ }
+
+ static synchronized BluetoothHealthProfileHandler getInstance(Context context,
+ BluetoothService service) {
+ if (sInstance == null) sInstance = new BluetoothHealthProfileHandler(context, service);
+ return sInstance;
+ }
+
+ boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+ Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
+ msg.obj = config;
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+ String path = mHealthAppConfigs.get(config);
+ if (path == null) return false;
+
+ Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_APPLICATION);
+ msg.obj = config;
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean connectChannelToSource(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ return connectChannel(device, config, BluetoothHealth.CHANNEL_TYPE_ANY);
+ }
+
+ private HealthChannel getMainChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ for (HealthChannel chan: mHealthChannels) {
+ if (chan.mDevice.equals(device) && chan.mConfig.equals(config)) {
+ if (chan.mMainChannel) return chan;
+ }
+ }
+ return null;
+ }
+
+ boolean connectChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int channelType) {
+ String deviceObjectPath =
+ mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ if (deviceObjectPath == null) return false;
+
+ String configPath = mHealthAppConfigs.get(config);
+ if (configPath == null) return false;
+
+ HealthChannel chan = new HealthChannel(device, config, null, false, null);
+ chan.mState = BluetoothHealth.STATE_CHANNEL_CONNECTING;
+ chan.mChannelType = channelType;
+ mHealthChannels.add(chan);
+
+ int prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ int state = BluetoothHealth.STATE_CHANNEL_CONNECTING;
+ callHealthChannelCallback(config, device, prevState, state, null);
+
+ Message msg = mHandler.obtainMessage(MESSAGE_CONNECT_CHANNEL);
+ msg.obj = chan;
+ mHandler.sendMessage(msg);
+
+ return true;
+ }
+
+ private String getStringChannelType(int type) {
+ if (type == BluetoothHealth.CHANNEL_TYPE_RELIABLE) {
+ return "Reliable";
+ } else if (type == BluetoothHealth.CHANNEL_TYPE_STREAMING) {
+ return "Streaming";
+ } else {
+ return "Any";
+ }
+ }
+
+ private String getStringRole(int role) {
+ if (role == BluetoothHealth.SINK_ROLE) {
+ return "Sink";
+ } else if (role == BluetoothHealth.SOURCE_ROLE) {
+ return "Streaming";
+ } else {
+ return null;
+ }
+ }
+
+ boolean disconnectChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ HealthChannel chan = findChannelByFd(device, config, fd);
+ if (chan == null) return false;
+
+ String deviceObjectPath =
+ mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ if (mBluetoothService.destroyChannelNative(deviceObjectPath, chan.mChannelPath)) {
+ int prevState = chan.mState;
+ chan.mState = BluetoothHealth.STATE_CHANNEL_DISCONNECTING;
+ callHealthChannelCallback(config, device, prevState, chan.mState,
+ chan.mChannelFd);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private HealthChannel findChannelByFd(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ for (HealthChannel chan : mHealthChannels) {
+ if (chan.mChannelFd.equals(fd) && chan.mDevice.equals(device) &&
+ chan.mConfig.equals(config)) return chan;
+ }
+ return null;
+ }
+
+ private HealthChannel findChannelByPath(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, String path) {
+ for (HealthChannel chan : mHealthChannels) {
+ if (chan.mChannelPath.equals(path) && chan.mDevice.equals(device) &&
+ chan.mConfig.equals(config)) return chan;
+ }
+ return null;
+ }
+
+ private List<HealthChannel> findChannelByStates(BluetoothDevice device, int[] states) {
+ List<HealthChannel> channels = new ArrayList<HealthChannel>();
+ for (HealthChannel chan: mHealthChannels) {
+ if (chan.mDevice.equals(device)) {
+ for (int state : states) {
+ if (chan.mState == state) {
+ channels.add(chan);
+ }
+ }
+ }
+ }
+ return channels;
+ }
+
+ private HealthChannel findConnectingChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ for (HealthChannel chan : mHealthChannels) {
+ if (chan.mDevice.equals(device) && chan.mConfig.equals(config) &&
+ chan.mState == BluetoothHealth.STATE_CHANNEL_CONNECTING) return chan;
+ }
+ return null;
+ }
+
+ ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ HealthChannel chan = getMainChannel(device, config);
+ if (chan != null) return chan.mChannelFd;
+
+ String objectPath =
+ mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ if (objectPath == null) return null;
+
+ String mainChannelPath = mBluetoothService.getMainChannelNative(objectPath);
+ if (mainChannelPath == null) return null;
+
+ // We had no record of the main channel but querying Bluez we got a
+ // main channel. We might not have received the PropertyChanged yet for
+ // the main channel creation so update our data structure here.
+ chan = findChannelByPath(device, config, mainChannelPath);
+ if (chan == null) {
+ errorLog("Main Channel present but we don't have any account of it:" +
+ device +":" + config);
+ return null;
+ }
+ chan.mMainChannel = true;
+ return chan.mChannelFd;
+ }
+
+ /*package*/ void onHealthDevicePropertyChanged(String devicePath,
+ String channelPath) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ String address = mBluetoothService.getAddressFromObjectPath(devicePath);
+ if (address == null) return;
+
+ //TODO: Fix this in Bluez
+ if (channelPath.equals("/")) {
+ // This means that the main channel is being destroyed.
+ return;
+ }
+
+ BluetoothDevice device = adapter.getRemoteDevice(address);
+ BluetoothHealthAppConfiguration config = findHealthApplication(device,
+ channelPath);
+ if (config != null) {
+ HealthChannel chan = findChannelByPath(device, config, channelPath);
+ if (chan == null) {
+ errorLog("Health Channel is not present:" + channelPath);
+ } else {
+ chan.mMainChannel = true;
+ }
+ }
+ }
+
+ private BluetoothHealthAppConfiguration findHealthApplication(
+ BluetoothDevice device, String channelPath) {
+ BluetoothHealthAppConfiguration config = null;
+ String configPath = mBluetoothService.getChannelApplicationNative(channelPath);
+
+ if (configPath == null) {
+ errorLog("No associated application for Health Channel:" + channelPath);
+ return null;
+ } else {
+ for (Entry<BluetoothHealthAppConfiguration, String> e :
+ mHealthAppConfigs.entrySet()) {
+ if (e.getValue().equals(configPath)) {
+ config = e.getKey();
+ }
+ }
+ if (config == null) {
+ errorLog("No associated application for application path:" + configPath);
+ return null;
+ }
+ }
+ return config;
+ }
+
+ /*package*/ void onHealthDeviceChannelChanged(String devicePath,
+ String channelPath, boolean exists) {
+ debugLog("onHealthDeviceChannelChanged: devicePath: " + devicePath +
+ "ChannelPath: " + channelPath + "Exists: " + exists);
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ String address = mBluetoothService.getAddressFromObjectPath(devicePath);
+ if (address == null) return;
+
+ BluetoothDevice device = adapter.getRemoteDevice(address);
+
+ BluetoothHealthAppConfiguration config = findHealthApplication(device,
+ channelPath);
+ int state, prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ ParcelFileDescriptor fd;
+ HealthChannel channel;
+
+ if (config != null) {
+ if (exists) {
+ fd = mBluetoothService.getChannelFdNative(channelPath);
+
+ if (fd == null) {
+ errorLog("Error obtaining fd for channel:" + channelPath);
+ return;
+ }
+
+ boolean mainChannel =
+ getMainChannel(device, config) == null ? false : true;
+ if (!mainChannel) {
+ String mainChannelPath =
+ mBluetoothService.getMainChannelNative(devicePath);
+ if (mainChannelPath == null) {
+ errorLog("Main Channel Path is null for devicePath:" + devicePath);
+ return;
+ }
+ if (mainChannelPath.equals(channelPath)) mainChannel = true;
+ }
+
+ channel = findConnectingChannel(device, config);
+ if (channel != null) {
+ channel.mChannelFd = fd;
+ channel.mMainChannel = mainChannel;
+ channel.mChannelPath = channelPath;
+ prevState = channel.mState;
+ } else {
+ channel = new HealthChannel(device, config, fd, mainChannel,
+ channelPath);
+ mHealthChannels.add(channel);
+ prevState = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ }
+ state = BluetoothHealth.STATE_CHANNEL_CONNECTED;
+ } else {
+ channel = findChannelByPath(device, config, channelPath);
+ if (channel == null) {
+ errorLog("Channel not found:" + config + ":" + channelPath);
+ return;
+ }
+
+ fd = channel.mChannelFd;
+ // CLOSE FD
+ mBluetoothService.releaseChannelFdNative(channel.mChannelPath);
+ mHealthChannels.remove(channel);
+
+ prevState = channel.mState;
+ state = BluetoothHealth.STATE_CHANNEL_DISCONNECTED;
+ }
+ channel.mState = state;
+ callHealthChannelCallback(config, device, prevState, state, fd);
+ }
+ }
+
+ private void callHealthChannelCallback(BluetoothHealthAppConfiguration config,
+ BluetoothDevice device, int prevState, int state, ParcelFileDescriptor fd) {
+ broadcastHealthDeviceStateChange(device, prevState, state);
+
+ debugLog("Health Device Callback: " + device + " State Change: "
+ + prevState + "->" + state);
+ try {
+ config.getCallback().onHealthChannelStateChange(config, device, prevState,
+ state, fd);
+ } catch (RemoteException e) {
+ errorLog("Error while making health channel state change callback: " + e);
+ }
+ }
+
+ private void callHealthApplicationStatusCallback(
+ BluetoothHealthAppConfiguration config, int status) {
+ debugLog("Health Device Application: " + config + " State Change: status:"
+ + status);
+ try {
+ config.getCallback().onHealthAppConfigurationStatusChange(config, status);
+ } catch (RemoteException e) {
+ errorLog("Error while making health app registration state change callback: " + e);
+ }
+ }
+
+ int getHealthDeviceConnectionState(BluetoothDevice device) {
+ if (mHealthDevices.get(device) == null) {
+ return BluetoothHealth.STATE_DISCONNECTED;
+ }
+ return mHealthDevices.get(device);
+ }
+
+ List<BluetoothDevice> getConnectedHealthDevices() {
+ List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(
+ new int[] {BluetoothHealth.STATE_CONNECTED});
+ return devices;
+ }
+
+ List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(int[] states) {
+ List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(states);
+ return devices;
+ }
+
+ List<BluetoothDevice> lookupHealthDevicesMatchingStates(int[] states) {
+ List<BluetoothDevice> healthDevices = new ArrayList<BluetoothDevice>();
+
+ for (BluetoothDevice device: mHealthDevices.keySet()) {
+ int healthDeviceState = getHealthDeviceConnectionState(device);
+ for (int state : states) {
+ if (state == healthDeviceState) {
+ healthDevices.add(device);
+ break;
+ }
+ }
+ }
+ return healthDevices;
+ }
+
+ /**
+ * This function sends the intent for the updates on the connection status to the remote device.
+ * Note that multiple channels can be connected to the remote device by multiple applications.
+ * This sends an intent for the update to the device connection status and not the channel
+ * connection status. Only the following state transitions are possible:
+ *
+ * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTING}
+ * {@link BluetoothHealth#STATE_CONNECTING} to {@link BluetoothHealth#STATE_CONNECTED}
+ * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTING}
+ * {@link BluetoothHealth#STATE_DISCONNECTING} to {@link BluetoothHealth#STATE_DISCONNECTED}
+ * {@link BluetoothHealth#STATE_DISCONNECTED} to {@link BluetoothHealth#STATE_CONNECTED}
+ * {@link BluetoothHealth#STATE_CONNECTED} to {@link BluetoothHealth#STATE_DISCONNECTED}
+ * {@link BluetoothHealth#STATE_CONNECTING} to {{@link BluetoothHealth#STATE_DISCONNECTED}
+ *
+ * @param device
+ * @param prevChannelState
+ * @param newChannelState
+ * @hide
+ */
+ private void broadcastHealthDeviceStateChange(BluetoothDevice device, int prevChannelState,
+ int newChannelState) {
+ if (mHealthDevices.get(device) == null) {
+ mHealthDevices.put(device, BluetoothHealth.STATE_DISCONNECTED);
+ }
+
+ int currDeviceState = mHealthDevices.get(device);
+ int newDeviceState = convertState(newChannelState);
+
+ if (currDeviceState != newDeviceState) {
+ List<HealthChannel> chan;
+ switch (currDeviceState) {
+ case BluetoothHealth.STATE_DISCONNECTED:
+ updateAndsendIntent(device, currDeviceState, newDeviceState);
+ break;
+ case BluetoothHealth.STATE_CONNECTING:
+ // Channel got connected.
+ if (newDeviceState == BluetoothHealth.STATE_CONNECTED) {
+ updateAndsendIntent(device, currDeviceState, newDeviceState);
+ } else {
+ // Channel got disconnected
+ chan = findChannelByStates(device, new int [] {
+ BluetoothHealth.STATE_CHANNEL_CONNECTING,
+ BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
+ if (chan.isEmpty()) {
+ updateAndsendIntent(device, currDeviceState, newDeviceState);
+ }
+ }
+ break;
+ case BluetoothHealth.STATE_CONNECTED:
+ // Channel got disconnected or is in disconnecting state.
+ chan = findChannelByStates(device, new int [] {
+ BluetoothHealth.STATE_CHANNEL_CONNECTING,
+ BluetoothHealth.STATE_CHANNEL_CONNECTED});
+ if (chan.isEmpty()) {
+ updateAndsendIntent(device, currDeviceState, newDeviceState);
+ }
+ case BluetoothHealth.STATE_DISCONNECTING:
+ // Channel got disconnected.
+ chan = findChannelByStates(device, new int [] {
+ BluetoothHealth.STATE_CHANNEL_CONNECTING,
+ BluetoothHealth.STATE_CHANNEL_DISCONNECTING});
+ if (chan.isEmpty()) {
+ updateAndsendIntent(device, currDeviceState, newDeviceState);
+ }
+ break;
+ }
+ }
+ }
+
+ private void updateAndsendIntent(BluetoothDevice device, int prevDeviceState,
+ int newDeviceState) {
+ mHealthDevices.put(device, newDeviceState);
+ mBluetoothService.sendConnectionStateChange(device, prevDeviceState, newDeviceState);
+ }
+
+ /**
+ * This function converts the channel connection state to device connection state.
+ *
+ * @param state
+ * @return
+ */
+ private int convertState(int state) {
+ switch (state) {
+ case BluetoothHealth.STATE_CHANNEL_CONNECTED:
+ return BluetoothHealth.STATE_CONNECTED;
+ case BluetoothHealth.STATE_CHANNEL_CONNECTING:
+ return BluetoothHealth.STATE_CONNECTING;
+ case BluetoothHealth.STATE_CHANNEL_DISCONNECTING:
+ return BluetoothHealth.STATE_DISCONNECTING;
+ case BluetoothHealth.STATE_CHANNEL_DISCONNECTED:
+ return BluetoothHealth.STATE_DISCONNECTED;
+ }
+ errorLog("Mismatch in Channel and Health Device State");
+ return -1;
+ }
+
+ private static void debugLog(String msg) {
+ if (DBG) Log.d(TAG, msg);
+ }
+
+ private static void errorLog(String msg) {
+ Log.e(TAG, msg);
+ }
+}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
old mode 100755
new mode 100644
index 62792f4..b5ae298
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -31,6 +31,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDeviceProfileState;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHealthAppConfiguration;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -49,6 +50,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -148,6 +150,7 @@
private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
private BluetoothPanProfileHandler mBluetoothPanProfileHandler;
private BluetoothInputProfileHandler mBluetoothInputProfileHandler;
+ private BluetoothHealthProfileHandler mBluetoothHealthProfileHandler;
private static class RemoteService {
public String address;
@@ -220,6 +223,7 @@
mContext.registerReceiver(mReceiver, filter);
mBluetoothInputProfileHandler = BluetoothInputProfileHandler.getInstance(mContext, this);
mBluetoothPanProfileHandler = BluetoothPanProfileHandler.getInstance(mContext, this);
+ mBluetoothHealthProfileHandler = BluetoothHealthProfileHandler.getInstance(mContext, this);
}
public static synchronized String readDockBluetoothAddress() {
@@ -566,7 +570,7 @@
mIsDiscovering = false;
mBondState.readAutoPairingData();
- mBondState.loadBondState();
+ mBondState.initBondState();
initProfileState();
// This should be the last step of the the enable thread.
@@ -1247,18 +1251,9 @@
return true;
}
- boolean ret;
- // Just do the SDP if the device is already created and UUIDs are not
- // NULL, else create the device and then do SDP.
- if (mDeviceProperties.isInCache(address) && getRemoteUuids(address) != null) {
- String path = getObjectPathFromAddress(address);
- if (path == null) return false;
-
- // Use an empty string for the UUID pattern
- ret = discoverServicesNative(path, "");
- } else {
- ret = createDeviceNative(address);
- }
+ // If the device is already created, we will
+ // do the SDP on the callback of createDeviceNative.
+ boolean ret= createDeviceNative(address);
mUuidIntentTracker.add(address);
if (uuid != null) {
@@ -2086,6 +2081,106 @@
}
}
+ /**** Handlers for Health Device Profile ****/
+ // TODO: All these need to be converted to a state machine.
+
+ public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.registerAppConfiguration(config);
+ }
+ }
+
+ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.unregisterAppConfiguration(config);
+ }
+ }
+
+
+ public boolean connectChannelToSource(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.connectChannelToSource(device,
+ config);
+ }
+ }
+
+ public boolean connectChannelToSink(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int channelType) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.connectChannel(device, config,
+ channelType);
+ }
+ }
+
+ public boolean disconnectChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, ParcelFileDescriptor fd) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.disconnectChannel(device, config, fd);
+ }
+ }
+
+ public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.getMainChannelFd(device, config);
+ }
+ }
+
+ /*package*/ void onHealthDevicePropertyChanged(String devicePath,
+ String channelPath) {
+ synchronized (mBluetoothHealthProfileHandler) {
+ mBluetoothHealthProfileHandler.onHealthDevicePropertyChanged(devicePath,
+ channelPath);
+ }
+ }
+
+ /*package*/ void onHealthDeviceChannelChanged(String devicePath,
+ String channelPath, boolean exists) {
+ synchronized(mBluetoothHealthProfileHandler) {
+ mBluetoothHealthProfileHandler.onHealthDeviceChannelChanged(devicePath,
+ channelPath, exists);
+ }
+ }
+
+ public int getHealthDeviceConnectionState(BluetoothDevice device) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.getHealthDeviceConnectionState(device);
+ }
+ }
+
+ public List<BluetoothDevice> getConnectedHealthDevices() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.getConnectedHealthDevices();
+ }
+ }
+
+ public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(
+ int[] states) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ synchronized (mBluetoothHealthProfileHandler) {
+ return mBluetoothHealthProfileHandler.
+ getHealthDevicesMatchingConnectionStates(states);
+ }
+ }
+
public boolean connectHeadset(String address) {
if (getBondState(address) != BluetoothDevice.BOND_BONDED) return false;
@@ -2384,4 +2479,16 @@
private native int[] addReservedServiceRecordsNative(int[] uuuids);
private native boolean removeReservedServiceRecordsNative(int[] handles);
+
+ // Health API
+ native String registerHealthApplicationNative(int dataType, String role, String name,
+ String channelType);
+ native String registerHealthApplicationNative(int dataType, String role, String name);
+ native boolean unregisterHealthApplicationNative(String path);
+ native boolean createChannelNative(String devicePath, String appPath, String channelType);
+ native boolean destroyChannelNative(String devicePath, String channelpath);
+ native String getMainChannelNative(String path);
+ native String getChannelApplicationNative(String channelPath);
+ native ParcelFileDescriptor getChannelFdNative(String channelPath);
+ native boolean releaseChannelFdNative(String channelPath);
}
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 3826a01..79ade260 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -23,10 +23,14 @@
import android.app.SearchableInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
import android.os.Process;
+import android.provider.Settings;
import android.util.Log;
import java.util.List;
@@ -46,6 +50,8 @@
// This field is initialized lazily in getSearchables(), and then never modified.
private Searchables mSearchables;
+ private ContentObserver mGlobalSearchObserver;
+
/**
* Initializes the Search Manager service in the provided system context.
* Only one instance of this object should be created!
@@ -56,6 +62,8 @@
mContext = context;
mContext.registerReceiver(new BootCompletedReceiver(),
new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ mGlobalSearchObserver = new GlobalSearchProviderObserver(
+ mContext.getContentResolver());
}
private synchronized Searchables getSearchables() {
@@ -100,6 +108,28 @@
}
}
+ class GlobalSearchProviderObserver extends ContentObserver {
+ private final ContentResolver mResolver;
+
+ public GlobalSearchProviderObserver(ContentResolver resolver) {
+ super(null);
+ mResolver = resolver;
+ mResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
+ false /* notifyDescendants */,
+ this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ getSearchables().buildSearchableList();
+ Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ mContext.sendBroadcast(intent);
+ }
+
+ }
+
//
// Searchable activities API
//
@@ -126,6 +156,10 @@
return getSearchables().getSearchablesInGlobalSearchList();
}
+ public List<ResolveInfo> getGlobalSearchActivities() {
+ return getSearchables().getGlobalSearchActivities();
+ }
+
/**
* Gets the name of the global search activity.
*/
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 279c17d..f24d52f 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,19 +16,23 @@
package android.server.search;
-import android.Manifest;
import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -50,7 +54,10 @@
private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
private ArrayList<SearchableInfo> mSearchablesList = null;
private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
- private ComponentName mGlobalSearchActivity = null;
+ // Contains all installed activities that handle the global search
+ // intent.
+ private List<ResolveInfo> mGlobalSearchActivities;
+ private ComponentName mCurrentGlobalSearchActivity = null;
private ComponentName mWebSearchActivity = null;
public static String GOOGLE_SEARCH_COMPONENT_NAME =
@@ -224,8 +231,11 @@
}
}
+ List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
+
// Find the global search activity
- ComponentName newGlobalSearchActivity = findGlobalSearchActivity();
+ ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
+ newGlobalSearchActivities);
// Find the web search activity
ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
@@ -235,38 +245,124 @@
mSearchablesMap = newSearchablesMap;
mSearchablesList = newSearchablesList;
mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
- mGlobalSearchActivity = newGlobalSearchActivity;
+ mGlobalSearchActivities = newGlobalSearchActivities;
+ mCurrentGlobalSearchActivity = newGlobalSearchActivity;
mWebSearchActivity = newWebSearchActivity;
}
}
-
/**
- * Finds the global search activity.
+ * Returns a sorted list of installed search providers as per
+ * the following heuristics:
*
- * This is currently implemented by returning the first activity that handles
- * the GLOBAL_SEARCH intent and has the GLOBAL_SEARCH permission. If we allow
- * more than one global search activity to be installed, this code must be changed.
+ * (a) System apps are given priority over non system apps.
+ * (b) Among system apps and non system apps, the relative ordering
+ * is defined by their declared priority.
*/
- private ComponentName findGlobalSearchActivity() {
+ private List<ResolveInfo> findGlobalSearchActivities() {
+ // Step 1 : Query the package manager for a list
+ // of activities that can handle the GLOBAL_SEARCH intent.
Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> activities =
pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
- int count = activities == null ? 0 : activities.size();
- for (int i = 0; i < count; i++) {
- ActivityInfo ai = activities.get(i).activityInfo;
- if (pm.checkPermission(Manifest.permission.GLOBAL_SEARCH,
- ai.packageName) == PackageManager.PERMISSION_GRANTED) {
- return new ComponentName(ai.packageName, ai.name);
- } else {
- Log.w(LOG_TAG, "Package " + ai.packageName + " wants to handle GLOBAL_SEARCH, "
- + "but does not have the GLOBAL_SEARCH permission.");
+
+ if (activities != null && !activities.isEmpty()) {
+ // Step 2: Rank matching activities according to our heuristics.
+ Collections.sort(activities, GLOBAL_SEARCH_RANKER);
+ }
+
+ return activities;
+ }
+
+ /**
+ * Finds the global search activity.
+ */
+ private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) {
+ // Fetch the global search provider from the system settings,
+ // and if it's still installed, return it.
+ final String searchProviderSetting = getGlobalSearchProviderSetting();
+ if (!TextUtils.isEmpty(searchProviderSetting)) {
+ final ComponentName globalSearchComponent = ComponentName.unflattenFromString(
+ searchProviderSetting);
+ if (globalSearchComponent != null && isInstalled(globalSearchComponent)) {
+ return globalSearchComponent;
}
}
+
+ return getDefaultGlobalSearchProvider(installed);
+ }
+
+ /**
+ * Checks whether the global search provider with a given
+ * component name is installed on the system or not. This deals with
+ * cases such as the removal of an installed provider.
+ */
+ private boolean isInstalled(ComponentName globalSearch) {
+ Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+ intent.setComponent(globalSearch);
+
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> activities =
+ pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ if (activities != null && !activities.isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER =
+ new Comparator<ResolveInfo>() {
+ @Override
+ public int compare(ResolveInfo lhs, ResolveInfo rhs) {
+ if (lhs == rhs) {
+ return 0;
+ }
+ boolean lhsSystem = isSystemApp(lhs);
+ boolean rhsSystem = isSystemApp(rhs);
+
+ if (lhsSystem && !rhsSystem) {
+ return -1;
+ } else if (rhsSystem && !lhsSystem) {
+ return 1;
+ } else {
+ // Either both system engines, or both non system
+ // engines.
+ //
+ // Note, this isn't a typo. Higher priority numbers imply
+ // higher priority, but are "lower" in the sort order.
+ return rhs.priority - lhs.priority;
+ }
+ }
+ };
+
+ /**
+ * @return true iff. the resolve info corresponds to a system application.
+ */
+ private static final boolean isSystemApp(ResolveInfo res) {
+ return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ }
+
+ /**
+ * Returns the highest ranked search provider as per the
+ * ranking defined in {@link #getGlobalSearchActivities()}.
+ */
+ private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) {
+ if (providerList != null && !providerList.isEmpty()) {
+ ActivityInfo ai = providerList.get(0).activityInfo;
+ return new ComponentName(ai.packageName, ai.name);
+ }
+
Log.w(LOG_TAG, "No global search activity found");
return null;
}
+ private String getGlobalSearchProviderSetting() {
+ return Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY);
+ }
+
/**
* Finds the web search activity.
*
@@ -281,9 +377,9 @@
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> activities =
pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
- int count = activities == null ? 0 : activities.size();
- for (int i = 0; i < count; i++) {
- ActivityInfo ai = activities.get(i).activityInfo;
+
+ if (activities != null && !activities.isEmpty()) {
+ ActivityInfo ai = activities.get(0).activityInfo;
// TODO: do some sanity checks here?
return new ComponentName(ai.packageName, ai.name);
}
@@ -307,10 +403,17 @@
}
/**
+ * Returns a list of activities that handle the global search intent.
+ */
+ public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() {
+ return new ArrayList<ResolveInfo>(mGlobalSearchActivities);
+ }
+
+ /**
* Gets the name of the global search activity.
*/
public synchronized ComponentName getGlobalSearchActivity() {
- return mGlobalSearchActivity;
+ return mCurrentGlobalSearchActivity;
}
/**
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 40e9355..8e4725f 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -234,6 +234,14 @@
public static final String INTENT_ACTION_TTS_SERVICE =
"android.intent.action.TTS_SERVICE";
+ /**
+ * Name under which a text to speech engine publishes information about itself.
+ * This meta-data should reference an XML resource containing a
+ * <code><{@link android.R.styleable#TextToSpeechEngine tts-engine}></code>
+ * tag.
+ */
+ public static final String SERVICE_META_DATA = "android.speech.tts";
+
// intents to ask engine to install data or check its data
/**
* Activity Action: Triggers the platform TextToSpeech engine to
@@ -434,7 +442,7 @@
private final Map<String, Uri> mUtterances;
private final Bundle mParams = new Bundle();
private final TtsEngines mEnginesHelper;
- private String mCurrentEngine = null;
+ private volatile String mCurrentEngine = null;
/**
* The constructor for the TextToSpeech class, using the default TTS engine.
@@ -565,6 +573,7 @@
service.setCallback(getPackageName(), null);
service.stop(getPackageName());
mServiceConnection.disconnect();
+ mCurrentEngine = null;
return null;
}
}, null, "shutdown");
@@ -861,6 +870,14 @@
}
/**
+ * @return the engine currently in use by this TextToSpeech instance.
+ * @hide
+ */
+ public String getCurrentEngine() {
+ return mCurrentEngine;
+ }
+
+ /**
* Sets the text-to-speech language.
* The TTS engine will try to use the closest match to the specified
* language as represented by the Locale, but there is no guarantee that the exact same Locale
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index ed9e048..5f0cb74 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -15,17 +15,27 @@
*/
package android.speech.tts;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.provider.Settings;
import android.speech.tts.TextToSpeech.Engine;
import android.speech.tts.TextToSpeech.EngineInfo;
import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -41,6 +51,8 @@
* @hide
*/
public class TtsEngines {
+ private static final String TAG = "TtsEngines";
+
private final Context mContext;
public TtsEngines(Context ctx) {
@@ -139,6 +151,89 @@
return getEngineInfo(engine) != null;
}
+ /**
+ * @return an intent that can launch the settings activity for a given tts engine.
+ */
+ public Intent getSettingsIntent(String engine) {
+ PackageManager pm = mContext.getPackageManager();
+ Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE);
+ intent.setPackage(engine);
+ List<ResolveInfo> resolveInfos = pm.queryIntentServices(intent,
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA);
+ // Note that the current API allows only one engine per
+ // package name. Since the "engine name" is the same as
+ // the package name.
+ if (resolveInfos != null && resolveInfos.size() == 1) {
+ ServiceInfo service = resolveInfos.get(0).serviceInfo;
+ if (service != null) {
+ final String settings = settingsActivityFromServiceInfo(service, pm);
+ if (settings != null) {
+ Intent i = new Intent();
+ i.setClassName(engine, settings);
+ return i;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * The name of the XML tag that text to speech engines must use to
+ * declare their meta data.
+ *
+ * {@link com.android.internal.R.styleable.TextToSpeechEngine}
+ */
+ private static final String XML_TAG_NAME = "tts-engine";
+
+ private String settingsActivityFromServiceInfo(ServiceInfo si, PackageManager pm) {
+ XmlResourceParser parser = null;
+ try {
+ parser = si.loadXmlMetaData(pm, TextToSpeech.Engine.SERVICE_META_DATA);
+ if (parser == null) {
+ Log.w(TAG, "No meta-data found for :" + si);
+ return null;
+ }
+
+ final Resources res = pm.getResourcesForApplication(si.applicationInfo);
+
+ int type;
+ while ((type = parser.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (type == XmlResourceParser.START_TAG) {
+ if (!XML_TAG_NAME.equals(parser.getName())) {
+ Log.w(TAG, "Package " + si + " uses unknown tag :"
+ + parser.getName());
+ return null;
+ }
+
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ final TypedArray array = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.TextToSpeechEngine);
+ final String settings = array.getString(
+ com.android.internal.R.styleable.TextToSpeechEngine_settingsActivity);
+ array.recycle();
+
+ return settings;
+ }
+ }
+
+ return null;
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Could not load resources for : " + si);
+ return null;
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Error parsing metadata for " + si + ":" + e);
+ return null;
+ } catch (IOException e) {
+ Log.w(TAG, "Error parsing metadata for " + si + ":" + e);
+ return null;
+ } finally {
+ if (parser != null) {
+ parser.close();
+ }
+ }
+ }
+
private EngineInfo getEngineInfo(ResolveInfo resolve, PackageManager pm) {
ServiceInfo service = resolve.serviceInfo;
if (service != null) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 4107c5a..aae9ccf 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -266,7 +266,7 @@
}
}
- Alignment align = mAlignment;
+ Alignment paraAlign = mAlignment;
TabStops tabStops = null;
boolean tabStopsIsInitialized = false;
@@ -310,10 +310,10 @@
ParagraphStyle.class);
spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
- align = mAlignment;
+ paraAlign = mAlignment;
for (int n = spans.length-1; n >= 0; n--) {
if (spans[n] instanceof AlignmentSpan) {
- align = ((AlignmentSpan) spans[n]).getAlignment();
+ paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
break;
}
}
@@ -360,6 +360,16 @@
tabStopsIsInitialized = true;
}
+ // Determine whether the line aligns to normal, opposite, or center.
+ Alignment align = paraAlign;
+ if (align == Alignment.ALIGN_LEFT) {
+ align = (dir == DIR_LEFT_TO_RIGHT) ?
+ Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
+ } else if (align == Alignment.ALIGN_RIGHT) {
+ align = (dir == DIR_LEFT_TO_RIGHT) ?
+ Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
+ }
+
int x;
if (align == Alignment.ALIGN_NORMAL) {
if (dir == DIR_LEFT_TO_RIGHT) {
@@ -411,7 +421,9 @@
int dir = getParagraphDirection(line);
int x;
- if (align == Alignment.ALIGN_NORMAL) {
+ if (align == Alignment.ALIGN_LEFT) {
+ x = left;
+ } else if (align == Alignment.ALIGN_NORMAL) {
if (dir == DIR_LEFT_TO_RIGHT) {
x = left;
} else {
@@ -430,7 +442,9 @@
}
}
int max = (int)getLineExtent(line, tabStops, false);
- if (align == Alignment.ALIGN_OPPOSITE) {
+ if (align == Alignment.ALIGN_RIGHT) {
+ x = right - max;
+ } else if (align == Alignment.ALIGN_OPPOSITE) {
if (dir == DIR_LEFT_TO_RIGHT) {
x = right - max;
} else {
@@ -738,11 +752,15 @@
int dir = getParagraphDirection(line);
Alignment align = getParagraphAlignment(line);
- if (align == Alignment.ALIGN_NORMAL) {
+ if (align == Alignment.ALIGN_LEFT) {
+ return 0;
+ } else if (align == Alignment.ALIGN_NORMAL) {
if (dir == DIR_RIGHT_TO_LEFT)
return getParagraphRight(line) - getLineMax(line);
else
return 0;
+ } else if (align == Alignment.ALIGN_RIGHT) {
+ return mWidth - getLineMax(line);
} else if (align == Alignment.ALIGN_OPPOSITE) {
if (dir == DIR_RIGHT_TO_LEFT)
return 0;
@@ -765,11 +783,15 @@
int dir = getParagraphDirection(line);
Alignment align = getParagraphAlignment(line);
- if (align == Alignment.ALIGN_NORMAL) {
+ if (align == Alignment.ALIGN_LEFT) {
+ return getParagraphLeft(line) + getLineMax(line);
+ } else if (align == Alignment.ALIGN_NORMAL) {
if (dir == DIR_RIGHT_TO_LEFT)
return mWidth;
else
return getParagraphLeft(line) + getLineMax(line);
+ } else if (align == Alignment.ALIGN_RIGHT) {
+ return mWidth;
} else if (align == Alignment.ALIGN_OPPOSITE) {
if (dir == DIR_RIGHT_TO_LEFT)
return getLineMax(line);
@@ -1765,8 +1787,10 @@
ALIGN_NORMAL,
ALIGN_OPPOSITE,
ALIGN_CENTER,
- // XXX ALIGN_LEFT,
- // XXX ALIGN_RIGHT,
+ /** @hide */
+ ALIGN_LEFT,
+ /** @hide */
+ ALIGN_RIGHT,
}
private static final int TAB_INCREMENT = 20;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d594567..519b980 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -119,13 +119,37 @@
* being applied.
* @hide
*/
- public int unscaledWidthPixels;
+ public int noncompatWidthPixels;
/**
* The reported display height prior to any compatibility mode scaling
* being applied.
* @hide
*/
- public int unscaledHeightPixels;
+ public int noncompatHeightPixels;
+ /**
+ * The reported display density prior to any compatibility mode scaling
+ * being applied.
+ * @hide
+ */
+ public float noncompatDensity;
+ /**
+ * The reported scaled density prior to any compatibility mode scaling
+ * being applied.
+ * @hide
+ */
+ public float noncompatScaledDensity;
+ /**
+ * The reported display xdpi prior to any compatibility mode scaling
+ * being applied.
+ * @hide
+ */
+ public float noncompatXdpi;
+ /**
+ * The reported display ydpi prior to any compatibility mode scaling
+ * being applied.
+ * @hide
+ */
+ public float noncompatYdpi;
public DisplayMetrics() {
}
@@ -138,8 +162,12 @@
scaledDensity = o.scaledDensity;
xdpi = o.xdpi;
ydpi = o.ydpi;
- unscaledWidthPixels = o.unscaledWidthPixels;
- unscaledHeightPixels = o.unscaledHeightPixels;
+ noncompatWidthPixels = o.noncompatWidthPixels;
+ noncompatHeightPixels = o.noncompatHeightPixels;
+ noncompatDensity = o.noncompatDensity;
+ noncompatScaledDensity = o.noncompatScaledDensity;
+ noncompatXdpi = o.noncompatXdpi;
+ noncompatYdpi = o.noncompatYdpi;
}
public void setToDefaults() {
@@ -150,8 +178,8 @@
scaledDensity = density;
xdpi = DENSITY_DEVICE;
ydpi = DENSITY_DEVICE;
- unscaledWidthPixels = 0;
- unscaledHeightPixels = 0;
+ noncompatWidthPixels = 0;
+ noncompatHeightPixels = 0;
}
@Override
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 3fa8dfd..2be5a49 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -107,8 +107,8 @@
CompatibilityInfo ci;
if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
synchronized (mTmpMetrics) {
- mTmpMetrics.unscaledWidthPixels = outSize.x;
- mTmpMetrics.unscaledHeightPixels = outSize.y;
+ mTmpMetrics.noncompatWidthPixels = outSize.x;
+ mTmpMetrics.noncompatHeightPixels = outSize.y;
mTmpMetrics.density = mDensity;
ci.applyToDisplayMetrics(mTmpMetrics);
outSize.x = mTmpMetrics.widthPixels;
@@ -268,14 +268,15 @@
}
private void getNonSizeMetrics(DisplayMetrics outMetrics) {
- outMetrics.density = mDensity;
outMetrics.densityDpi = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
- outMetrics.scaledDensity= outMetrics.density;
- outMetrics.xdpi = mDpiX;
- outMetrics.ydpi = mDpiY;
- outMetrics.unscaledWidthPixels = outMetrics.widthPixels;
- outMetrics.unscaledHeightPixels = outMetrics.heightPixels;
+ outMetrics.noncompatWidthPixels = outMetrics.widthPixels;
+ outMetrics.noncompatHeightPixels = outMetrics.heightPixels;
+
+ outMetrics.density = outMetrics.noncompatDensity = mDensity;
+ outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
+ outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
+ outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
}
static IWindowManager getWindowManager() {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5216c49..04f35dc 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -161,10 +161,11 @@
// Hardware layers
///////////////////////////////////////////////////////////////////////////
- static native int nCreateTextureLayer(int[] layerInfo);
+ static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
- static native void nUpdateTextureLayer(int layerId, int width, int height, SurfaceTexture surface);
+ static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
+ SurfaceTexture surface);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
static native boolean nCopyLayer(int layerId, int bitmap);
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 69dfc2b..a491a0b 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -42,9 +42,15 @@
return mLayer;
}
+ @Override
boolean copyInto(Bitmap bitmap) {
return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
- }
+ }
+
+ @Override
+ void update(int width, int height, boolean isOpaque) {
+ super.update(width, height, isOpaque);
+ }
@Override
void destroy() {
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 063eee7..391d9f4 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -28,9 +28,9 @@
private int mTexture;
private SurfaceTexture mSurface;
- GLES20TextureLayer() {
+ GLES20TextureLayer(boolean isOpaque) {
int[] layerInfo = new int[2];
- mLayer = GLES20Canvas.nCreateTextureLayer(layerInfo);
+ mLayer = GLES20Canvas.nCreateTextureLayer(isOpaque, layerInfo);
if (mLayer != 0) {
mTexture = layerInfo[0];
@@ -65,12 +65,14 @@
SurfaceTexture getSurfaceTexture() {
if (mSurface == null) {
- mSurface = new SurfaceTexture(mTexture);
+ mSurface = new SurfaceTexture(mTexture, false);
}
return mSurface;
}
- void update(int width, int height) {
- GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, mSurface);
+ @Override
+ void update(int width, int height, boolean isOpaque) {
+ super.update(width, height, isOpaque);
+ GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface);
}
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 86dec3f..dfb39ae 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
@@ -34,7 +35,7 @@
int mWidth;
int mHeight;
- final boolean mOpaque;
+ boolean mOpaque;
/**
* Creates a new hardware layer with undefined dimensions.
@@ -92,7 +93,7 @@
abstract boolean isValid();
/**
- * Resizes the layer, if necessary, to be at least as large
+ * Resize the layer, if necessary, to be at least as large
* as the supplied dimensions.
*
* @param width The new desired minimum width for this layer
@@ -124,4 +125,29 @@
* @param currentCanvas
*/
abstract void end(Canvas currentCanvas);
+
+ /**
+ * Copies this layer into the specified bitmap.
+ *
+ * @param bitmap The bitmap to copy they layer into
+ *
+ * @return True if the copy was successful, false otherwise
+ */
+ abstract boolean copyInto(Bitmap bitmap);
+
+ /**
+ * Update the layer's properties. This method should be used
+ * when the underlying storage is modified by an external entity.
+ * To change the underlying storage, use the {@link #resize(int, int)}
+ * method instead.
+ *
+ * @param width The new width of this layer
+ * @param height The new height of this layer
+ * @param isOpaque Whether this layer is opaque
+ */
+ void update(int width, int height, boolean isOpaque) {
+ mWidth = width;
+ mHeight = height;
+ mOpaque = isOpaque;
+ }
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 5ceb12a..bbfb4c1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -17,12 +17,11 @@
package android.view;
-import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.os.*;
-import android.util.EventLog;
+import android.os.SystemClock;
+import android.os.SystemProperties;
import android.util.Log;
import javax.microedition.khronos.egl.EGL10;
@@ -170,9 +169,11 @@
* Creates a new hardware layer. A hardware layer built by calling this
* method will be treated as a texture layer, instead of as a render target.
*
+ * @param isOpaque Whether the layer should be opaque or not
+ *
* @return A hardware layer
*/
- abstract HardwareLayer createHardwareLayer();
+ abstract HardwareLayer createHardwareLayer(boolean isOpaque);
/**
* Creates a new hardware layer.
@@ -197,25 +198,6 @@
abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
/**
- * Updates the specified layer.
- *
- * @param layer The hardware layer to update
- * @param width The layer's width
- * @param height The layer's height
- */
- abstract void updateTextureLayer(HardwareLayer layer, int width, int height);
-
- /**
- * Copies the content of the specified layer into the specified bitmap.
- *
- * @param layer The hardware layer to copy
- * @param bitmap The bitmap to copy the layer into
- *
- * @return True if the copy was successful, false otherwise
- */
- abstract boolean copyLayer(HardwareLayer layer, Bitmap bitmap);
-
- /**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
* potentially lost the hardware renderer. The hardware renderer should be
@@ -339,6 +321,13 @@
}
/**
+ * Indicates whether this renderer instance can track and update dirty regions.
+ */
+ boolean hasDirtyRegions() {
+ return mDirtyRegions;
+ }
+
+ /**
* Return a string for the EGL error code, or the hex representation
* if the error is unknown.
*
@@ -631,19 +620,14 @@
void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
Rect dirty) {
if (canDraw()) {
- if (!mDirtyRegions) {
+ if (!hasDirtyRegions()) {
dirty = null;
}
-
- attachInfo.mDrawingTime = SystemClock.uptimeMillis();
attachInfo.mIgnoreDirtyState = true;
+ attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+
view.mPrivateFlags |= View.DRAWN;
- long startTime;
- if (ViewDebug.DEBUG_PROFILE_DRAWING) {
- startTime = SystemClock.elapsedRealtime();
- }
-
final int surfaceState = checkCurrent();
if (surfaceState != SURFACE_STATE_ERROR) {
// We had to change the current surface and/or context, redraw everything
@@ -697,26 +681,9 @@
onPostDraw();
- if (ViewDebug.DEBUG_PROFILE_DRAWING) {
- EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
- }
-
attachInfo.mIgnoreDirtyState = false;
- final long swapBuffersStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
- swapBuffersStartTime = System.nanoTime();
- }
-
sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
-
- if (ViewDebug.DEBUG_LATENCY) {
- long now = System.nanoTime();
- Log.d(LOG_TAG, "Latency: Spent "
- + ((now - swapBuffersStartTime) * 0.000001f)
- + "ms waiting for eglSwapBuffers()");
- }
-
checkEglErrors();
}
}
@@ -803,8 +770,8 @@
}
@Override
- HardwareLayer createHardwareLayer() {
- return new GLES20TextureLayer();
+ HardwareLayer createHardwareLayer(boolean isOpaque) {
+ return new GLES20TextureLayer(isOpaque);
}
@Override
@@ -817,16 +784,6 @@
return ((GLES20TextureLayer) layer).getSurfaceTexture();
}
- @Override
- void updateTextureLayer(HardwareLayer layer, int width, int height) {
- ((GLES20TextureLayer) layer).update(width, height);
- }
-
- @Override
- boolean copyLayer(HardwareLayer layer, Bitmap bitmap) {
- return ((GLES20Layer) layer).copyInto(bitmap);
- }
-
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
return new Gl20Renderer(translucent);
diff --git a/core/java/android/view/InputEventConsistencyVerifier.java b/core/java/android/view/InputEventConsistencyVerifier.java
index e14b975..9b081b2 100644
--- a/core/java/android/view/InputEventConsistencyVerifier.java
+++ b/core/java/android/view/InputEventConsistencyVerifier.java
@@ -32,6 +32,11 @@
public final class InputEventConsistencyVerifier {
private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE);
+ private static final String EVENT_TYPE_KEY = "KeyEvent";
+ private static final String EVENT_TYPE_TRACKBALL = "TrackballEvent";
+ private static final String EVENT_TYPE_TOUCH = "TouchEvent";
+ private static final String EVENT_TYPE_GENERIC_MOTION = "GenericMotionEvent";
+
// The number of recent events to log when a problem is detected.
// Can be set to 0 to disable logging recent events but the runtime overhead of
// this feature is negligible on current hardware.
@@ -54,6 +59,7 @@
// It does not make sense to examine the contents of the last event since it may have
// been recycled.
private InputEvent mLastEvent;
+ private String mLastEventType;
private int mLastNestingLevel;
// Copy of the most recent events.
@@ -185,7 +191,7 @@
* and both dispatching methods call into the consistency verifier.
*/
public void onKeyEvent(KeyEvent event, int nestingLevel) {
- if (!startEvent(event, nestingLevel, "KeyEvent")) {
+ if (!startEvent(event, nestingLevel, EVENT_TYPE_KEY)) {
return;
}
@@ -233,7 +239,7 @@
break;
}
} finally {
- finishEvent(false);
+ finishEvent();
}
}
@@ -247,7 +253,7 @@
* and both dispatching methods call into the consistency verifier.
*/
public void onTrackballEvent(MotionEvent event, int nestingLevel) {
- if (!startEvent(event, nestingLevel, "TrackballEvent")) {
+ if (!startEvent(event, nestingLevel, EVENT_TYPE_TRACKBALL)) {
return;
}
@@ -296,7 +302,7 @@
problem("Source was not SOURCE_CLASS_TRACKBALL.");
}
} finally {
- finishEvent(false);
+ finishEvent();
}
}
@@ -310,22 +316,20 @@
* and both dispatching methods call into the consistency verifier.
*/
public void onTouchEvent(MotionEvent event, int nestingLevel) {
- if (!startEvent(event, nestingLevel, "TouchEvent")) {
+ if (!startEvent(event, nestingLevel, EVENT_TYPE_TOUCH)) {
return;
}
final int action = event.getAction();
final boolean newStream = action == MotionEvent.ACTION_DOWN
|| action == MotionEvent.ACTION_CANCEL;
- if (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled) {
- if (newStream) {
- mTouchEventStreamIsTainted = false;
- mTouchEventStreamUnhandled = false;
- mTouchEventStreamPointers = 0;
- } else {
- finishEvent(mTouchEventStreamIsTainted);
- return;
- }
+ if (newStream && (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled)) {
+ mTouchEventStreamIsTainted = false;
+ mTouchEventStreamUnhandled = false;
+ mTouchEventStreamPointers = 0;
+ }
+ if (mTouchEventStreamIsTainted) {
+ event.setTainted(true);
}
try {
@@ -439,7 +443,7 @@
problem("Source was not SOURCE_CLASS_POINTER.");
}
} finally {
- finishEvent(false);
+ finishEvent();
}
}
@@ -453,7 +457,7 @@
* and both dispatching methods call into the consistency verifier.
*/
public void onGenericMotionEvent(MotionEvent event, int nestingLevel) {
- if (!startEvent(event, nestingLevel, "GenericMotionEvent")) {
+ if (!startEvent(event, nestingLevel, EVENT_TYPE_GENERIC_MOTION)) {
return;
}
@@ -497,7 +501,7 @@
}
}
} finally {
- finishEvent(false);
+ finishEvent();
}
}
@@ -568,21 +572,19 @@
}
private boolean startEvent(InputEvent event, int nestingLevel, String eventType) {
- // Ignore the event if it is already tainted.
- if (event.isTainted()) {
- return false;
- }
-
// Ignore the event if we already checked it at a higher nesting level.
- if (event == mLastEvent && nestingLevel < mLastNestingLevel) {
+ if (event == mLastEvent && nestingLevel < mLastNestingLevel
+ && eventType == mLastEventType) {
return false;
}
if (nestingLevel > 0) {
mLastEvent = event;
+ mLastEventType = eventType;
mLastNestingLevel = nestingLevel;
} else {
mLastEvent = null;
+ mLastEventType = null;
mLastNestingLevel = 0;
}
@@ -591,35 +593,35 @@
return true;
}
- private void finishEvent(boolean tainted) {
+ private void finishEvent() {
if (mViolationMessage != null && mViolationMessage.length() != 0) {
- mViolationMessage.append("\n in ").append(mCaller);
- mViolationMessage.append("\n ");
- appendEvent(mViolationMessage, 0, mCurrentEvent, false);
+ if (!mCurrentEvent.isTainted()) {
+ // Write a log message only if the event was not already tainted.
+ mViolationMessage.append("\n in ").append(mCaller);
+ mViolationMessage.append("\n ");
+ appendEvent(mViolationMessage, 0, mCurrentEvent, false);
- if (RECENT_EVENTS_TO_LOG != 0 && mRecentEvents != null) {
- mViolationMessage.append("\n -- recent events --");
- for (int i = 0; i < RECENT_EVENTS_TO_LOG; i++) {
- final int index = (mMostRecentEventIndex + RECENT_EVENTS_TO_LOG - i)
- % RECENT_EVENTS_TO_LOG;
- final InputEvent event = mRecentEvents[index];
- if (event == null) {
- break;
+ if (RECENT_EVENTS_TO_LOG != 0 && mRecentEvents != null) {
+ mViolationMessage.append("\n -- recent events --");
+ for (int i = 0; i < RECENT_EVENTS_TO_LOG; i++) {
+ final int index = (mMostRecentEventIndex + RECENT_EVENTS_TO_LOG - i)
+ % RECENT_EVENTS_TO_LOG;
+ final InputEvent event = mRecentEvents[index];
+ if (event == null) {
+ break;
+ }
+ mViolationMessage.append("\n ");
+ appendEvent(mViolationMessage, i + 1, event, mRecentEventsUnhandled[index]);
}
- mViolationMessage.append("\n ");
- appendEvent(mViolationMessage, i + 1, event, mRecentEventsUnhandled[index]);
}
+
+ Log.d(mLogTag, mViolationMessage.toString());
+
+ // Taint the event so that we do not generate additional violations from it
+ // further downstream.
+ mCurrentEvent.setTainted(true);
}
-
- Log.d(mLogTag, mViolationMessage.toString());
mViolationMessage.setLength(0);
- tainted = true;
- }
-
- if (tainted) {
- // Taint the event so that we do not generate additional violations from it
- // further downstream.
- mCurrentEvent.setTainted(true);
}
if (RECENT_EVENTS_TO_LOG != 0) {
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 5dbda90..6c3d387 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2361,11 +2361,11 @@
* Gets the {@link KeyCharacterMap} associated with the keyboard device.
*
* @return The associated key character map.
- * @throws {@link UnavailableException} if the key character map
+ * @throws {@link KeyCharacterMap.UnavailableException} if the key character map
* could not be loaded because it was malformed or the default key character map
* is missing from the system.
*
- * @see {@link KeyCharacterMap#load}
+ * @see KeyCharacterMap#load
*/
public final KeyCharacterMap getKeyCharacterMap() {
return KeyCharacterMap.load(mDeviceId);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 3436cd1..88f59d4 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1130,14 +1130,14 @@
public static final int BUTTON_PRIMARY = 1 << 0;
/**
- * Button constant: Secondary button (right mouse button, stylus barrel).
+ * Button constant: Secondary button (right mouse button, stylus first button).
*
* @see #getButtonState
*/
public static final int BUTTON_SECONDARY = 1 << 1;
/**
- * Button constant: Tertiary button (middle mouse button).
+ * Button constant: Tertiary button (middle mouse button, stylus second button).
*
* @see #getButtonState
*/
@@ -1165,13 +1165,6 @@
*/
public static final int BUTTON_FORWARD = 1 << 4;
- /**
- * Button constant: Eraser button pressed (stylus end).
- *
- * @see #getButtonState
- */
- public static final int BUTTON_ERASER = 1 << 5;
-
// NOTE: If you add a new axis here you must also add it to:
// native/include/android/input.h
@@ -1183,7 +1176,7 @@
"BUTTON_TERTIARY",
"BUTTON_BACK",
"BUTTON_FORWARD",
- "BUTTON_ERASER",
+ "0x00000020",
"0x00000040",
"0x00000080",
"0x00000100",
@@ -2176,7 +2169,6 @@
* @see #BUTTON_TERTIARY
* @see #BUTTON_FORWARD
* @see #BUTTON_BACK
- * @see #BUTTON_ERASER
*/
public final int getButtonState() {
return nativeGetButtonState(mNativePtr);
@@ -2893,7 +2885,7 @@
toolTypeToString(getToolType(i)));
}
- msg.append(", buttonState=").append(KeyEvent.metaStateToString(getButtonState()));
+ msg.append(", buttonState=").append(MotionEvent.buttonStateToString(getButtonState()));
msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState()));
msg.append(", flags=0x").append(Integer.toHexString(getFlags()));
msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags()));
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 164c657..d656f31 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -67,15 +67,19 @@
* // Something bad happened
* }
* }
- *
+ *
* public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
* // Ignored, Camera does all the work for us
* }
- *
+ *
* public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
* mCamera.stopPreview();
* mCamera.release();
* }
+ *
+ * public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ * // Invoked every time there's a new Camera preview frame
+ * }
* }
* </pre>
*
@@ -96,12 +100,11 @@
private SurfaceTexture mSurface;
private SurfaceTextureListener mListener;
- private final Runnable mUpdateLayerAction = new Runnable() {
- @Override
- public void run() {
- updateLayer();
- }
- };
+ private boolean mOpaque = true;
+
+ private final Object[] mLock = new Object[0];
+ private boolean mUpdateLayer;
+
private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
/**
@@ -146,6 +149,28 @@
mLayerPaint = new Paint();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isOpaque() {
+ return mOpaque;
+ }
+
+ /**
+ * Indicates whether the content of this TextureView is opaque. The
+ * content is assumed to be opaque by default.
+ *
+ * @param opaque True if the content of this TextureView is opaque,
+ * false otherwise
+ */
+ public void setOpaque(boolean opaque) {
+ if (opaque != mOpaque) {
+ mOpaque = opaque;
+ updateLayer();
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -160,7 +185,7 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (isHardwareAccelerated() && mLayer != null) {
+ if (mLayer != null) {
if (mListener != null) {
mListener.onSurfaceTextureDestroyed(mSurface);
}
@@ -215,7 +240,7 @@
*/
@Override
public final void draw(Canvas canvas) {
- super.draw(canvas);
+ applyUpdate();
}
/**
@@ -241,12 +266,12 @@
@Override
HardwareLayer getHardwareLayer() {
- if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
- return null;
- }
-
if (mLayer == null) {
- mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer();
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ return null;
+ }
+
+ mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
@@ -255,7 +280,10 @@
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
// Per SurfaceTexture's documentation, the callback may be invoked
// from an arbitrary thread
- post(mUpdateLayerAction);
+ synchronized (mLock) {
+ mUpdateLayer = true;
+ }
+ postInvalidateDelayed(0);
}
};
mSurface.setOnFrameAvailableListener(mUpdateListener);
@@ -265,6 +293,8 @@
}
}
+ applyUpdate();
+
return mLayer;
}
@@ -286,13 +316,28 @@
}
private void updateLayer() {
- if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ mUpdateLayer = true;
+ invalidate();
+ }
+
+ private void applyUpdate() {
+ if (mLayer == null) {
return;
}
- mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight());
+ synchronized (mLock) {
+ if (mUpdateLayer) {
+ mUpdateLayer = false;
+ } else {
+ return;
+ }
+ }
+
+ mLayer.update(getWidth(), getHeight(), mOpaque);
- invalidate();
+ if (mListener != null) {
+ mListener.onSurfaceTextureUpdated(mSurface);
+ }
}
/**
@@ -306,6 +351,8 @@
* <p><strong>Do not</strong> invoke this method from a drawing method
* ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
*
+ * <p>If an error occurs during the copy, an empty bitmap will be returned.</p>
+ *
* @return A valid {@link Bitmap.Config#ARGB_8888} bitmap, or null if the surface
* texture is not available or the width <= 0 or the height <= 0
*
@@ -328,6 +375,8 @@
* <p><strong>Do not</strong> invoke this method from a drawing method
* ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
*
+ * <p>If an error occurs during the copy, an empty bitmap will be returned.</p>
+ *
* @param width The width of the bitmap to create
* @param height The height of the bitmap to create
*
@@ -354,6 +403,8 @@
* <p><strong>Do not</strong> invoke this method from a drawing method
* ({@link #onDraw(android.graphics.Canvas)} for instance).</p>
*
+ * <p>If an error occurs, the bitmap is left unchanged.</p>
+ *
* @param bitmap The bitmap to copy the content of the surface texture into,
* cannot be null, all configurations are supported
*
@@ -365,7 +416,7 @@
*/
public Bitmap getBitmap(Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
- mAttachInfo.mHardwareRenderer.copyLayer(mLayer, bitmap);
+ mLayer.copyInto(bitmap);
}
return bitmap;
}
@@ -445,7 +496,16 @@
* @param surface The surface about to be destroyed
*/
public void onSurfaceTextureDestroyed(SurfaceTexture surface);
+
+ /**
+ * Invoked when the specified {@link SurfaceTexture} is updated through
+ * {@link SurfaceTexture#updateTexImage()}.
+ *
+ * @param surface The surface just updated
+ */
+ public void onSurfaceTextureUpdated(SurfaceTexture surface);
}
- private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture, int width, int height);
+ private static native void nSetDefaultBufferSize(SurfaceTexture surfaceTexture,
+ int width, int height);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b0e651a..bb5c954 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -345,7 +345,7 @@
* 2 pixels to the right of the left edge. Padding can be set using the
* {@link #setPadding(int, int, int, int)} method and queried by calling
* {@link #getPaddingLeft()}, {@link #getPaddingTop()},
- * {@link #getPaddingRight()} and {@link #getPaddingBottom()}.
+ * {@link #getPaddingRight()}, {@link #getPaddingBottom()}.
* </p>
*
* <p>
@@ -607,6 +607,8 @@
* @attr ref android.R.styleable#View_paddingLeft
* @attr ref android.R.styleable#View_paddingRight
* @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
* @attr ref android.R.styleable#View_saveEnabled
* @attr ref android.R.styleable#View_rotation
* @attr ref android.R.styleable#View_rotationX
@@ -1734,11 +1736,20 @@
static final int DRAG_HOVERED = 0x00000002;
/**
- * Indicates whether the view is drawn in right-to-left direction.
+ * Indicates whether the view layout direction has been resolved and drawn to the
+ * right-to-left direction.
*
* @hide
*/
- static final int RESOLVED_LAYOUT_RTL = 0x00000004;
+ static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
+
+ /**
+ * Indicates whether the view layout direction has been resolved.
+ *
+ * @hide
+ */
+ static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
+
/* End of masks for mPrivateFlags2 */
@@ -2173,6 +2184,27 @@
int mUserPaddingLeft;
/**
+ * Cache if the user padding is relative.
+ *
+ */
+ @ViewDebug.ExportedProperty(category = "padding")
+ boolean mUserPaddingRelative;
+
+ /**
+ * Cache the paddingStart set by the user to append to the scrollbar's size.
+ *
+ */
+ @ViewDebug.ExportedProperty(category = "padding")
+ int mUserPaddingStart;
+
+ /**
+ * Cache the paddingEnd set by the user to append to the scrollbar's size.
+ *
+ */
+ @ViewDebug.ExportedProperty(category = "padding")
+ int mUserPaddingEnd;
+
+ /**
* @hide
*/
int mOldWidthMeasureSpec = Integer.MIN_VALUE;
@@ -2230,6 +2262,8 @@
private OnTouchListener mOnTouchListener;
+ private OnHoverListener mOnHoverListener;
+
private OnGenericMotionListener mOnGenericMotionListener;
private OnDragListener mOnDragListener;
@@ -2292,6 +2326,7 @@
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
+ private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
private UnsetPressedState mUnsetPressedState;
@@ -2452,6 +2487,90 @@
Rect mLocalDirtyRect;
/**
+ * Set to true when the view is sending hover accessibility events because it
+ * is the innermost hovered view.
+ */
+ private boolean mSendingHoverAccessibilityEvents;
+
+ /**
+ * Undefined text direction (used by resolution algorithm).
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_UNDEFINED = -1;
+
+ /**
+ * Text direction is inherited thru {@link ViewGroup}
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_INHERIT = 0;
+
+ /**
+ * Text direction is using "first strong algorithm". The first strong directional character
+ * determines the paragraph direction. If there is no strong directional character, the
+ * paragraph direction is the view’s resolved ayout direction.
+ *
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
+
+ /**
+ * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
+ * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
+ * If there are neither, the paragraph direction is the view’s resolved layout direction.
+ *
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_ANY_RTL = 2;
+
+ /**
+ * Text direction is forced to LTR.
+ *
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_LTR = 3;
+
+ /**
+ * Text direction is forced to RTL.
+ *
+ * @hide
+ */
+ public static final int TEXT_DIRECTION_RTL = 4;
+
+ /**
+ * Default text direction is inherited
+ */
+ protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
+
+ /**
+ * The text direction that has been defined by {@link #setTextDirection(int)}.
+ *
+ * {@hide}
+ */
+ @ViewDebug.ExportedProperty(category = "text", mapping = {
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+ })
+ protected int mTextDirection = DEFAULT_TEXT_DIRECTION;
+
+ /**
+ * The resolved text direction. If resolution has not yet been done or has been reset, it will
+ * be equal to {@link #TEXT_DIRECTION_UNDEFINED}. Otherwise it will be either {@link #TEXT_DIRECTION_LTR}
+ * or {@link #TEXT_DIRECTION_RTL}.
+ *
+ * {@hide}
+ */
+ @ViewDebug.ExportedProperty(category = "text", mapping = {
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_UNDEFINED, to = "UNDEFINED"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
+ @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
+ })
+ protected int mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+
+ /**
* Consistency verifier for debugging purposes.
* @hide
*/
@@ -2471,6 +2590,9 @@
mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
+ mUserPaddingStart = -1;
+ mUserPaddingEnd = -1;
+ mUserPaddingRelative = false;
}
/**
@@ -2523,6 +2645,8 @@
int topPadding = -1;
int rightPadding = -1;
int bottomPadding = -1;
+ int startPadding = -1;
+ int endPadding = -1;
int padding = -1;
@@ -2568,6 +2692,12 @@
case com.android.internal.R.styleable.View_paddingBottom:
bottomPadding = a.getDimensionPixelSize(attr, -1);
break;
+ case com.android.internal.R.styleable.View_paddingStart:
+ startPadding = a.getDimensionPixelSize(attr, -1);
+ break;
+ case com.android.internal.R.styleable.View_paddingEnd:
+ endPadding = a.getDimensionPixelSize(attr, -1);
+ break;
case com.android.internal.R.styleable.View_scrollX:
x = a.getDimensionPixelOffset(attr, 0);
break;
@@ -2813,6 +2943,9 @@
case R.styleable.View_layerType:
setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
break;
+ case R.styleable.View_textDirection:
+ mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
+ break;
}
}
@@ -2822,6 +2955,13 @@
setBackgroundDrawable(background);
}
+ mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0);
+
+ // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
+ // layout direction). Those cached values will be used later during padding resolution.
+ mUserPaddingStart = startPadding;
+ mUserPaddingEnd = endPadding;
+
if (padding >= 0) {
leftPadding = padding;
topPadding = padding;
@@ -3059,7 +3199,7 @@
}
// Re-apply user/background padding so that scrollbar(s) get added
- recomputePadding();
+ resolvePadding();
}
/**
@@ -3084,7 +3224,7 @@
if (mVerticalScrollbarPosition != position) {
mVerticalScrollbarPosition = position;
computeOpaqueFlags();
- recomputePadding();
+ resolvePadding();
}
}
@@ -3331,6 +3471,14 @@
}
/**
+ * Register a callback to be invoked when a hover event is sent to this view.
+ * @param l the hover listener to attach to this view
+ */
+ public void setOnHoverListener(OnHoverListener l) {
+ mOnHoverListener = l;
+ }
+
+ /**
* Register a drag event listener callback object for this View. The parameter is
* an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
* View, the system calls the
@@ -3641,7 +3789,6 @@
* @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
*/
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-
}
/**
@@ -3670,12 +3817,23 @@
event.setEnabled(isEnabled());
event.setContentDescription(mContentDescription);
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
- ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
- getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
- event.setItemCount(focusablesTempList.size());
- event.setCurrentItemIndex(focusablesTempList.indexOf(this));
- focusablesTempList.clear();
+ final int eventType = event.getEventType();
+ switch (eventType) {
+ case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+ if (mAttachInfo != null) {
+ ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
+ getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
+ FOCUSABLES_ALL);
+ event.setItemCount(focusablesTempList.size());
+ event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+ focusablesTempList.clear();
+ }
+ } break;
+ case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+ event.setScrollX(mScrollX);
+ event.setScrollY(mScrollY);
+ event.setItemCount(getHeight());
+ } break;
}
}
@@ -4287,19 +4445,25 @@
}
/**
- * Set the layout direction for this view.
+ * Set the layout direction for this view. This will propagate a reset of layout direction
+ * resolution to the view's children and resolve layout direction for this view.
*
* @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
* {@link #LAYOUT_DIRECTION_RTL},
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
+ *
* @attr ref android.R.styleable#View_layoutDirection
*
* @hide
*/
@RemotableViewMethod
public void setLayoutDirection(int layoutDirection) {
- setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
+ if (getLayoutDirection() != layoutDirection) {
+ resetLayoutDirectionResolution();
+ // Setting the flag will also request a layout.
+ setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
+ }
}
/**
@@ -4315,8 +4479,8 @@
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
})
public int getResolvedLayoutDirection() {
- resolveLayoutDirection();
- return ((mPrivateFlags2 & RESOLVED_LAYOUT_RTL) == RESOLVED_LAYOUT_RTL) ?
+ resolveLayoutDirectionIfNeeded();
+ return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
}
@@ -5063,15 +5227,7 @@
mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
}
- //Log.i("view", "view=" + this + ", " + event.toString());
- if (onTrackballEvent(event)) {
- return true;
- }
-
- if (mInputEventConsistencyVerifier != null) {
- mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
- }
- return false;
+ return onTrackballEvent(event);
}
/**
@@ -5098,6 +5254,12 @@
|| action == MotionEvent.ACTION_HOVER_MOVE
|| action == MotionEvent.ACTION_HOVER_EXIT) {
if (dispatchHoverEvent(event)) {
+ // For compatibility with existing applications that handled HOVER_MOVE
+ // events in onGenericMotionEvent, dispatch the event there. The
+ // onHoverEvent method did not exist at the time.
+ if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ dispatchGenericMotionEventInternal(event);
+ }
return true;
}
} else if (dispatchGenericPointerEvent(event)) {
@@ -5107,6 +5269,17 @@
return true;
}
+ if (dispatchGenericMotionEventInternal(event)) {
+ return true;
+ }
+
+ if (mInputEventConsistencyVerifier != null) {
+ mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
+ }
+ return false;
+ }
+
+ private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
//noinspection SimplifiableIfStatement
if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& mOnGenericMotionListener.onGenericMotion(this, event)) {
@@ -5132,13 +5305,43 @@
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
- * @hide
*/
protected boolean dispatchHoverEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ if (!hasHoveredChild() && !mSendingHoverAccessibilityEvents) {
+ mSendingHoverAccessibilityEvents = true;
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ if (mSendingHoverAccessibilityEvents) {
+ mSendingHoverAccessibilityEvents = false;
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+ }
+ break;
+ }
+
+ //noinspection SimplifiableIfStatement
+ if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
+ && mOnHoverListener.onHover(this, event)) {
+ return true;
+ }
+
return onHoverEvent(event);
}
/**
+ * Returns true if the view has a child to which it has recently sent
+ * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
+ * it does not have a hovered child, then it must be the innermost hovered view.
+ * @hide
+ */
+ protected boolean hasHoveredChild() {
+ return false;
+ }
+
+ /**
* Dispatch a generic motion event to the view under the first pointer.
* <p>
* Do not call this method directly.
@@ -5147,7 +5350,6 @@
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
- * @hide
*/
protected boolean dispatchGenericPointerEvent(MotionEvent event) {
return false;
@@ -5162,7 +5364,6 @@
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
- * @hide
*/
protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
return false;
@@ -5739,71 +5940,130 @@
/**
* Implement this method to handle hover events.
* <p>
- * Hover events are pointer events with action {@link MotionEvent#ACTION_HOVER_ENTER},
- * {@link MotionEvent#ACTION_HOVER_MOVE}, or {@link MotionEvent#ACTION_HOVER_EXIT}.
+ * This method is called whenever a pointer is hovering into, over, or out of the
+ * bounds of a view and the view is not currently being touched.
+ * Hover events are represented as pointer events with action
+ * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
+ * or {@link MotionEvent#ACTION_HOVER_EXIT}.
+ * </p>
+ * <ul>
+ * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
+ * when the pointer enters the bounds of the view.</li>
+ * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
+ * when the pointer has already entered the bounds of the view and has moved.</li>
+ * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
+ * when the pointer has exited the bounds of the view or when the pointer is
+ * about to go down due to a button click, tap, or similar user action that
+ * causes the view to be touched.</li>
+ * </ul>
+ * <p>
+ * The view should implement this method to return true to indicate that it is
+ * handling the hover event, such as by changing its drawable state.
* </p><p>
- * The view receives hover enter as the pointer enters the bounds of the view and hover
- * exit as the pointer exits the bound of the view or just before the pointer goes down
- * (which implies that {@link #onTouchEvent(MotionEvent)} will be called soon).
- * </p><p>
- * If the view would like to handle the hover event itself and prevent its children
- * from receiving hover, it should return true from this method. If this method returns
- * true and a child has already received a hover enter event, the child will
- * automatically receive a hover exit event.
- * </p><p>
- * The default implementation sets the hovered state of the view if the view is
- * clickable.
+ * The default implementation calls {@link #setHovered} to update the hovered state
+ * of the view when a hover enter or hover exit event is received, if the view
+ * is enabled and is clickable.
* </p>
*
* @param event The motion event that describes the hover.
- * @return True if this view handled the hover event and does not want its children
- * to receive the hover event.
+ * @return True if the view handled the hover event.
+ *
+ * @see #isHovered
+ * @see #setHovered
+ * @see #onHoverChanged
*/
public boolean onHoverEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- setHovered(true);
- break;
+ if (isHoverable()) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ setHovered(true);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ setHovered(false);
+ break;
+ }
+ return true;
+ }
+ return false;
+ }
- case MotionEvent.ACTION_HOVER_EXIT:
- setHovered(false);
- break;
+ /**
+ * Returns true if the view should handle {@link #onHoverEvent}
+ * by calling {@link #setHovered} to change its hovered state.
+ *
+ * @return True if the view is hoverable.
+ */
+ private boolean isHoverable() {
+ final int viewFlags = mViewFlags;
+ //noinspection SimplifiableIfStatement
+ if ((viewFlags & ENABLED_MASK) == DISABLED) {
+ return false;
}
- return false;
+ return (viewFlags & CLICKABLE) == CLICKABLE
+ || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
}
/**
* Returns true if the view is currently hovered.
*
* @return True if the view is currently hovered.
+ *
+ * @see #setHovered
+ * @see #onHoverChanged
*/
+ @ViewDebug.ExportedProperty
public boolean isHovered() {
return (mPrivateFlags & HOVERED) != 0;
}
/**
* Sets whether the view is currently hovered.
+ * <p>
+ * Calling this method also changes the drawable state of the view. This
+ * enables the view to react to hover by using different drawable resources
+ * to change its appearance.
+ * </p><p>
+ * The {@link #onHoverChanged} method is called when the hovered state changes.
+ * </p>
*
* @param hovered True if the view is hovered.
+ *
+ * @see #isHovered
+ * @see #onHoverChanged
*/
public void setHovered(boolean hovered) {
if (hovered) {
if ((mPrivateFlags & HOVERED) == 0) {
mPrivateFlags |= HOVERED;
refreshDrawableState();
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+ onHoverChanged(true);
}
} else {
if ((mPrivateFlags & HOVERED) != 0) {
mPrivateFlags &= ~HOVERED;
refreshDrawableState();
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+ onHoverChanged(false);
}
}
}
/**
+ * Implement this method to handle hover state changes.
+ * <p>
+ * This method is called whenever the hover state changes as a result of a
+ * call to {@link #setHovered}.
+ * </p>
+ *
+ * @param hovered The current hover state, as returned by {@link #isHovered}.
+ *
+ * @see #isHovered
+ * @see #setHovered
+ */
+ public void onHoverChanged(boolean hovered) {
+ }
+
+ /**
* Implement this method to handle touch screen motion events.
*
* @param event The motion event.
@@ -6005,6 +6265,16 @@
}
/**
+ * Remove the pending callback for sending a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private void removeSendViewScrolledAccessibilityEventCallback() {
+ if (mSendViewScrolledAccessibilityEvent != null) {
+ removeCallbacks(mSendViewScrolledAccessibilityEvent);
+ }
+ }
+
+ /**
* Sets the TouchDelegate for this View.
*/
public void setTouchDelegate(TouchDelegate delegate) {
@@ -6089,7 +6359,11 @@
/* Check if the VISIBLE bit has changed */
if ((changed & INVISIBLE) != 0) {
needGlobalAttributesUpdate(false);
- invalidate(true);
+ /*
+ * If this view is becoming invisible, set the DRAWN flag so that
+ * the next invalidate() will not be skipped.
+ */
+ mPrivateFlags |= DRAWN;
if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
// root view becoming invisible shouldn't clear focus
@@ -6173,6 +6447,10 @@
* @param oldt Previous vertical scroll origin.
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ postSendViewScrolledAccessibilityEventCallback();
+ }
+
mBackgroundSizeChanged = true;
final AttachInfo ai = mAttachInfo;
@@ -8099,6 +8377,22 @@
}
/**
+ * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
+ * This event is sent at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
+ */
+ private void postSendViewScrolledAccessibilityEventCallback() {
+ if (mSendViewScrolledAccessibilityEvent == null) {
+ mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
+ }
+ if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
+ mSendViewScrolledAccessibilityEvent.mIsPending = true;
+ postDelayed(mSendViewScrolledAccessibilityEvent,
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+ }
+ }
+
+ /**
* Called by a parent to request that a child update its values for mScrollX
* and mScrollY if necessary. This will typically be done if the child is
* animating a scroll using a {@link android.widget.Scroller Scroller}
@@ -8261,7 +8555,7 @@
if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_HORIZONTAL;
computeOpaqueFlags();
- recomputePadding();
+ resolvePadding();
}
}
@@ -8291,7 +8585,7 @@
if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_VERTICAL;
computeOpaqueFlags();
- recomputePadding();
+ resolvePadding();
}
}
@@ -8350,7 +8644,7 @@
if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
computeOpaqueFlags();
- recomputePadding();
+ resolvePadding();
}
}
@@ -8735,35 +9029,109 @@
mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
}
jumpDrawablesToCurrentState();
- resolveLayoutDirection();
+ resetLayoutDirectionResolution();
+ resolveLayoutDirectionIfNeeded();
+ resolvePadding();
+ resetResolvedTextDirection();
+ resolveTextDirection();
+ if (isFocused()) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ imm.focusIn(this);
+ }
}
/**
- * Resolving the layout direction. LTR is set initially.
- * We are supposing here that the parent directionality will be resolved before its children.
+ * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
+ * that the parent directionality can and will be resolved before its children.
*/
- private void resolveLayoutDirection() {
- mPrivateFlags2 &= ~RESOLVED_LAYOUT_RTL;
+ private void resolveLayoutDirectionIfNeeded() {
+ // Do not resolve if it is not needed
+ if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
+
+ // Clear any previous layout direction resolution
+ mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
+
+ // Set resolved depending on layout direction
switch (getLayoutDirection()) {
case LAYOUT_DIRECTION_INHERIT:
// If this is root view, no need to look at parent's layout dir.
if (mParent != null &&
mParent instanceof ViewGroup &&
((ViewGroup) mParent).getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
- mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
+ mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
case LAYOUT_DIRECTION_RTL:
- mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
+ mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
break;
case LAYOUT_DIRECTION_LOCALE:
if(isLayoutDirectionRtl(Locale.getDefault())) {
- mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
+ mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
default:
// Nothing to do, LTR by default
}
+
+ // Set to resolved
+ mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
+ }
+
+ private void resolvePadding() {
+ // If the user specified the absolute padding (either with android:padding or
+ // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
+ // use the default padding or the padding from the background drawable
+ // (stored at this point in mPadding*)
+ switch (getResolvedLayoutDirection()) {
+ case LAYOUT_DIRECTION_RTL:
+ // Start user padding override Right user padding. Otherwise, if Right user
+ // padding is not defined, use the default Right padding. If Right user padding
+ // is defined, just use it.
+ if (mUserPaddingStart >= 0) {
+ mUserPaddingRight = mUserPaddingStart;
+ } else if (mUserPaddingRight < 0) {
+ mUserPaddingRight = mPaddingRight;
+ }
+ if (mUserPaddingEnd >= 0) {
+ mUserPaddingLeft = mUserPaddingEnd;
+ } else if (mUserPaddingLeft < 0) {
+ mUserPaddingLeft = mPaddingLeft;
+ }
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ // Start user padding override Left user padding. Otherwise, if Left user
+ // padding is not defined, use the default left padding. If Left user padding
+ // is defined, just use it.
+ if (mUserPaddingStart > 0) {
+ mUserPaddingLeft = mUserPaddingStart;
+ } else if (mUserPaddingLeft < 0) {
+ mUserPaddingLeft = mPaddingLeft;
+ }
+ if (mUserPaddingEnd > 0) {
+ mUserPaddingRight = mUserPaddingEnd;
+ } else if (mUserPaddingRight < 0) {
+ mUserPaddingRight = mPaddingRight;
+ }
+ }
+
+ mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
+
+ recomputePadding();
+ }
+
+ /**
+ * Reset the resolved layout direction.
+ *
+ * Subclasses need to override this method to clear cached information that depends on the
+ * resolved layout direction, or to inform child views that inherit their layout direction.
+ * Overrides must also call the superclass implementation at the start of their implementation.
+ *
+ * @hide
+ */
+ protected void resetLayoutDirectionResolution() {
+ // Reset the current View resolution
+ mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
}
/**
@@ -8772,7 +9140,7 @@
* @param locale Locale to check
* @return true if a Locale is corresponding to a RTL script.
*/
- private static boolean isLayoutDirectionRtl(Locale locale) {
+ protected static boolean isLayoutDirectionRtl(Locale locale) {
return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
LocaleUtil.getLayoutDirectionFromLocale(locale));
}
@@ -8789,6 +9157,7 @@
removeUnsetPressCallback();
removeLongPressCallback();
removePerformClickCallback();
+ removeSendViewScrolledAccessibilityEventCallback();
destroyDrawingCache();
@@ -9448,10 +9817,10 @@
computeScroll();
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~DIRTY_MASK;
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- mPrivateFlags &= ~DIRTY_MASK;
dispatchDraw(canvas);
} else {
draw(canvas);
@@ -10737,7 +11106,14 @@
sThreadLocal.set(padding);
}
if (d.getPadding(padding)) {
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ switch (d.getResolvedLayoutDirectionSelf()) {
+ case LAYOUT_DIRECTION_RTL:
+ setPadding(padding.right, padding.top, padding.left, padding.bottom);
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
}
// Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
@@ -10823,6 +11199,8 @@
public void setPadding(int left, int top, int right, int bottom) {
boolean changed = false;
+ mUserPaddingRelative = false;
+
mUserPaddingLeft = left;
mUserPaddingRight = right;
mUserPaddingBottom = bottom;
@@ -10832,11 +11210,16 @@
// Common case is there are no scroll bars.
if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
- // TODO Determine what to do with SCROLLBAR_POSITION_DEFAULT based on RTL settings.
final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
? 0 : getVerticalScrollbarWidth();
switch (mVerticalScrollbarPosition) {
case SCROLLBAR_POSITION_DEFAULT:
+ if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ left += offset;
+ } else {
+ right += offset;
+ }
+ break;
case SCROLLBAR_POSITION_RIGHT:
right += offset;
break;
@@ -10874,6 +11257,41 @@
}
/**
+ * Sets the relative padding. The view may add on the space required to display
+ * the scrollbars, depending on the style and visibility of the scrollbars.
+ * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
+ * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
+ * from the values set in this call.
+ *
+ * @attr ref android.R.styleable#View_padding
+ * @attr ref android.R.styleable#View_paddingBottom
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
+ * @attr ref android.R.styleable#View_paddingTop
+ * @param start the start padding in pixels
+ * @param top the top padding in pixels
+ * @param end the end padding in pixels
+ * @param bottom the bottom padding in pixels
+ *
+ * @hide
+ */
+ public void setPaddingRelative(int start, int top, int end, int bottom) {
+ mUserPaddingRelative = true;
+
+ mUserPaddingStart = start;
+ mUserPaddingEnd = end;
+
+ switch(getResolvedLayoutDirection()) {
+ case LAYOUT_DIRECTION_RTL:
+ setPadding(end, top, start, bottom);
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ setPadding(start, top, end, bottom);
+ }
+ }
+
+ /**
* Returns the top padding of this view.
*
* @return the top padding in pixels
@@ -10905,6 +11323,20 @@
}
/**
+ * Returns the start padding of this view. If there are inset and enabled
+ * scrollbars, this value may include the space required to display the
+ * scrollbars as well.
+ *
+ * @return the start padding in pixels
+ *
+ * @hide
+ */
+ public int getPaddingStart() {
+ return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+ mPaddingRight : mPaddingLeft;
+ }
+
+ /**
* Returns the right padding of this view. If there are inset and enabled
* scrollbars, this value may include the space required to display the
* scrollbars as well.
@@ -10916,6 +11348,34 @@
}
/**
+ * Returns the end padding of this view. If there are inset and enabled
+ * scrollbars, this value may include the space required to display the
+ * scrollbars as well.
+ *
+ * @return the end padding in pixels
+ *
+ * @hide
+ */
+ public int getPaddingEnd() {
+ return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+ mPaddingLeft : mPaddingRight;
+ }
+
+ /**
+ * Return if the padding as been set thru relative values
+ * {@link #setPaddingRelative(int, int, int, int)} or thru
+ * @attr ref android.R.styleable#View_paddingStart or
+ * @attr ref android.R.styleable#View_paddingEnd
+ *
+ * @return true if the padding is relative or false if it is not.
+ *
+ * @hide
+ */
+ public boolean isPaddingRelative() {
+ return mUserPaddingRelative;
+ }
+
+ /**
* Changes the selection state of this view. A view can be selected or not.
* Note that selection is not the same as focus. Views are typically
* selected in the context of an AdapterView like ListView or GridView;
@@ -11509,6 +11969,10 @@
mPrivateFlags |= FORCE_LAYOUT;
mPrivateFlags |= INVALIDATED;
+ if (mLayoutParams != null) {
+ mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
+ }
+
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
@@ -11701,7 +12165,7 @@
/**
* Utility to return a default size. Uses the supplied size if the
- * MeasureSpec imposed no contraints. Will get larger if allowed
+ * MeasureSpec imposed no constraints. Will get larger if allowed
* by the MeasureSpec.
*
* @param size Default size for this view
@@ -11711,7 +12175,7 @@
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
@@ -12523,6 +12987,89 @@
return getVerticalScrollFactor();
}
+ /**
+ * Return the value specifying the text direction or policy that was set with
+ * {@link #setTextDirection(int)}.
+ *
+ * @return the defined text direction. It can be one of:
+ *
+ * {@link #TEXT_DIRECTION_INHERIT},
+ * {@link #TEXT_DIRECTION_FIRST_STRONG}
+ * {@link #TEXT_DIRECTION_ANY_RTL},
+ * {@link #TEXT_DIRECTION_LTR},
+ * {@link #TEXT_DIRECTION_RTL},
+ *
+ * @hide
+ */
+ public int getTextDirection() {
+ return mTextDirection;
+ }
+
+ /**
+ * Set the text direction.
+ *
+ * @param textDirection the direction to set. Should be one of:
+ *
+ * {@link #TEXT_DIRECTION_INHERIT},
+ * {@link #TEXT_DIRECTION_FIRST_STRONG}
+ * {@link #TEXT_DIRECTION_ANY_RTL},
+ * {@link #TEXT_DIRECTION_LTR},
+ * {@link #TEXT_DIRECTION_RTL},
+ *
+ * @hide
+ */
+ public void setTextDirection(int textDirection) {
+ if (textDirection != mTextDirection) {
+ mTextDirection = textDirection;
+ resetResolvedTextDirection();
+ requestLayout();
+ }
+ }
+
+ /**
+ * Return the resolved text direction.
+ *
+ * @return the resolved text direction. Return one of:
+ *
+ * {@link #TEXT_DIRECTION_LTR},
+ * {@link #TEXT_DIRECTION_RTL},
+ *
+ * @hide
+ */
+ public int getResolvedTextDirection() {
+ if (!isResolvedTextDirection()) {
+ resolveTextDirection();
+ }
+ return mResolvedTextDirection;
+ }
+
+ /**
+ * Resolve the text direction. Classes that extend View and want to do a specific text direction
+ * resolution will need to implement this method and set the mResolvedTextDirection to
+ * either TEXT_DIRECTION_LTR if direction is LTR or TEXT_DIRECTION_RTL if
+ * direction is RTL.
+ */
+ protected void resolveTextDirection() {
+ }
+
+ /**
+ * Return if the text direction has been resolved or not.
+ *
+ * @return true, if resolved and false if not resolved
+ *
+ * @hide
+ */
+ public boolean isResolvedTextDirection() {
+ return (mResolvedTextDirection != TEXT_DIRECTION_UNDEFINED);
+ }
+
+ /**
+ * Reset resolved text direction. Will be resolved during a call to getResolvedLayoutDirection().
+ */
+ protected void resetResolvedTextDirection() {
+ mResolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+ }
+
//
// Properties
//
@@ -12530,7 +13077,7 @@
* A Property wrapper around the <code>alpha</code> functionality handled by the
* {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
*/
- static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
+ public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
@Override
public void setValue(View object, float value) {
object.setAlpha(value);
@@ -12892,6 +13439,24 @@
}
/**
+ * Interface definition for a callback to be invoked when a hover event is
+ * dispatched to this view. The callback will be invoked before the hover
+ * event is given to the view.
+ */
+ public interface OnHoverListener {
+ /**
+ * Called when a hover event is dispatched to a view. This allows listeners to
+ * get a chance to respond before the target view.
+ *
+ * @param v The view the hover event has been dispatched to.
+ * @param event The MotionEvent object containing full information about
+ * the event.
+ * @return True if the listener has consumed the event, false otherwise.
+ */
+ boolean onHover(View v, MotionEvent event);
+ }
+
+ /**
* Interface definition for a callback to be invoked when a generic motion event is
* dispatched to this view. The callback will be invoked before the generic motion
* event is given to the view.
@@ -13238,6 +13803,12 @@
boolean mIgnoreDirtyState;
/**
+ * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
+ * to avoid clearing that flag prematurely.
+ */
+ boolean mSetIgnoreDirtyState = false;
+
+ /**
* Indicates whether the view's window is currently in touch mode.
*/
boolean mInTouchMode;
@@ -13471,6 +14042,18 @@
host.invalidate(true);
}
}
+ }
+ /**
+ * Resuable callback for sending
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private class SendViewScrolledAccessibilityEvent implements Runnable {
+ public volatile boolean mIsPending;
+
+ public void run() {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ mIsPending = false;
+ }
}
}
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index ba3ae58..d70c798 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -136,13 +136,6 @@
static final ArrayList<ComponentCallbacks> sConfigCallbacks
= new ArrayList<ComponentCallbacks>();
- /**
- * Delay before dispatching an accessibility event that the window
- * content has changed. The window content is considered changed
- * after a layout pass.
- */
- private static final long SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS = 500;
-
long mLastTrackballTime = 0;
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -284,7 +277,7 @@
AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
- SendWindowContentChanged mSendWindowContentChanged;
+ SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
private final int mDensity;
@@ -672,6 +665,7 @@
}
}
if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
+ mAttachInfo.mSetIgnoreDirtyState = true;
mAttachInfo.mIgnoreDirtyState = true;
}
mDirty.union(dirty);
@@ -1000,8 +994,7 @@
+ "x" + desiredWindowHeight + "...");
boolean goodMeasure = false;
- if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
- || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
+ if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
// On large screens, we don't want to allow dialogs to just
// stretch to fill the entire width of the screen to display
// one line of text. First try doing the layout at a smaller
@@ -1748,7 +1741,7 @@
mAttachInfo.mIgnoreDirtyState = true;
dirty.union(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
}
-
+
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
if (!dirty.isEmpty() || mIsAnimating) {
mIsAnimating = false;
@@ -1878,9 +1871,13 @@
}
canvas.setScreenDensity(scalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
+ mAttachInfo.mSetIgnoreDirtyState = false;
mView.draw(canvas);
} finally {
- mAttachInfo.mIgnoreDirtyState = false;
+ if (!mAttachInfo.mSetIgnoreDirtyState) {
+ // Only clear the flag if it was not set during the mView.draw() call
+ mAttachInfo.mIgnoreDirtyState = false;
+ }
}
if (false && ViewDebug.consistencyCheckEnabled) {
@@ -3688,14 +3685,19 @@
/**
* Post a callback to send a
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+ * This event is send at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
*/
private void postSendWindowContentChangedCallback() {
- if (mSendWindowContentChanged == null) {
- mSendWindowContentChanged = new SendWindowContentChanged();
- } else {
- removeCallbacks(mSendWindowContentChanged);
+ if (mSendWindowContentChangedAccessibilityEvent == null) {
+ mSendWindowContentChangedAccessibilityEvent =
+ new SendWindowContentChangedAccessibilityEvent();
}
- postDelayed(mSendWindowContentChanged, SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS);
+ if (!mSendWindowContentChangedAccessibilityEvent.mIsPending) {
+ mSendWindowContentChangedAccessibilityEvent.mIsPending = true;
+ postDelayed(mSendWindowContentChangedAccessibilityEvent,
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+ }
}
/**
@@ -3703,8 +3705,8 @@
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
*/
private void removeSendWindowContentChangedCallback() {
- if (mSendWindowContentChanged != null) {
- removeCallbacks(mSendWindowContentChanged);
+ if (mSendWindowContentChangedAccessibilityEvent != null) {
+ removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
}
}
@@ -4479,7 +4481,7 @@
ArrayList<View> foundViews = mAttachInfo.mFocusablesTempList;
foundViews.clear();
- View root = null;
+ View root;
if (accessibilityViewId != View.NO_ID) {
root = findViewByAccessibilityId(accessibilityViewId);
} else {
@@ -4630,10 +4632,24 @@
}
}
- private class SendWindowContentChanged implements Runnable {
+ private class SendWindowContentChangedAccessibilityEvent implements Runnable {
+ public volatile boolean mIsPending;
+
public void run() {
if (mView != null) {
- mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ // Check again for accessibility state since this is executed delayed.
+ AccessibilityManager accessibilityManager =
+ AccessibilityManager.getInstance(mView.mContext);
+ if (accessibilityManager.isEnabled()) {
+ // Send the event directly since we do not want to append the
+ // source text because this is the text for the entire window
+ // and we just want to notify that the content has changed.
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ mView.onInitializeAccessibilityEvent(event);
+ accessibilityManager.sendAccessibilityEvent(event);
+ }
+ mIsPending = false;
}
}
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5919150..dbcbd6e 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -19,6 +19,8 @@
import android.app.AppGlobals;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.RemoteException;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.SparseArray;
@@ -176,6 +178,14 @@
private static final int TOUCH_EXPLORATION_TAP_SLOP = 80;
/**
+ * Delay before dispatching a recurring accessibility event in milliseconds.
+ * This delay guarantees that a recurring event will be send at most once
+ * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time
+ * frame.
+ */
+ private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400;
+
+ /**
* The maximum size of View's drawing cache, expressed in bytes. This size
* should be at least equal to the size of the screen in ARGB888 format.
*/
@@ -211,6 +221,9 @@
private final int mOverscrollDistance;
private final int mOverflingDistance;
+ private boolean sHasPermanentMenuKey;
+ private boolean sHasPermanentMenuKeySet;
+
private static final SparseArray<ViewConfiguration> sConfigurations =
new SparseArray<ViewConfiguration>(2);
@@ -246,11 +259,12 @@
* @see android.util.DisplayMetrics
*/
private ViewConfiguration(Context context) {
- final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+ final Resources res = context.getResources();
+ final DisplayMetrics metrics = res.getDisplayMetrics();
+ final Configuration config = res.getConfiguration();
final float density = metrics.density;
final float sizeAndDensity;
- if (context.getResources().getConfiguration().isLayoutSizeAtLeast(
- Configuration.SCREENLAYOUT_SIZE_XLARGE)) {
+ if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) {
sizeAndDensity = density * 1.5f;
} else {
sizeAndDensity = density;
@@ -272,6 +286,17 @@
mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
+
+ if (!sHasPermanentMenuKeySet) {
+ IWindowManager wm = Display.getWindowManager();
+ try {
+ sHasPermanentMenuKey = wm.canStatusBarHide() && !res.getBoolean(
+ com.android.internal.R.bool.config_showNavigationBar);
+ sHasPermanentMenuKeySet = true;
+ } catch (RemoteException ex) {
+ sHasPermanentMenuKey = false;
+ }
+ }
}
/**
@@ -498,6 +523,19 @@
}
/**
+ * Interval for dispatching a recurring accessibility event in milliseconds.
+ * This interval guarantees that a recurring event will be send at most once
+ * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
+ *
+ * @return The delay in milliseconds.
+ *
+ * @hide
+ */
+ public static long getSendRecurringAccessibilityEventsInterval() {
+ return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
+ }
+
+ /**
* @return Distance a touch must be outside the bounds of a window for it
* to be counted as outside the window for purposes of dismissing that
* window.
@@ -619,4 +657,20 @@
public static float getScrollFriction() {
return SCROLL_FRICTION;
}
+
+ /**
+ * Report if the device has a permanent menu key available to the user.
+ *
+ * <p>As of Android 3.0, devices may not have a permanent menu key available.
+ * Apps should use the action bar to present menu options to users.
+ * However, there are some apps where the action bar is inappropriate
+ * or undesirable. This method may be used to detect if a menu key is present.
+ * If not, applications should provide another on-screen affordance to access
+ * functionality.
+ *
+ * @return true if a permanent menu key is present, false otherwise.
+ */
+ public boolean hasPermanentMenuKey() {
+ return sHasPermanentMenuKey;
+ }
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a6bce75..da88fbb 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -46,6 +46,7 @@
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Locale;
/**
* <p>
@@ -143,8 +144,16 @@
@ViewDebug.ExportedProperty(category = "events")
private float mLastTouchDownY;
- // Child which last received ACTION_HOVER_ENTER and ACTION_HOVER_MOVE.
- private View mHoveredChild;
+ // First hover target in the linked list of hover targets.
+ // The hover targets are children which have received ACTION_HOVER_ENTER.
+ // They might not have actually handled the hover event, but we will
+ // continue sending hover events to them as long as the pointer remains over
+ // their bounds and the view group does not intercept hover.
+ private HoverTarget mFirstHoverTarget;
+
+ // True if the view group itself received a hover event.
+ // It might not have actually handled the hover event.
+ private boolean mHoveredSelf;
/**
* Internal flags.
@@ -1222,56 +1231,32 @@
return false;
}
- /** @hide */
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings({"ConstantConditions"})
@Override
protected boolean dispatchHoverEvent(MotionEvent event) {
- // Send the hover enter or hover move event to the view group first.
- // If it handles the event then a hovered child should receive hover exit.
- boolean handled = false;
- final boolean interceptHover;
final int action = event.getAction();
- if (action == MotionEvent.ACTION_HOVER_EXIT) {
- interceptHover = true;
- } else {
- handled = super.dispatchHoverEvent(event);
- interceptHover = handled;
- }
- // Send successive hover events to the hovered child as long as the pointer
- // remains within the child's bounds.
+ // First check whether the view group wants to intercept the hover event.
+ final boolean interceptHover = onInterceptHoverEvent(event);
+ event.setAction(action); // restore action in case it was changed
+
MotionEvent eventNoHistory = event;
- if (mHoveredChild != null) {
+ boolean handled = false;
+
+ // Send events to the hovered children and build a new list of hover targets until
+ // one is found that handles the event.
+ HoverTarget firstOldHoverTarget = mFirstHoverTarget;
+ mFirstHoverTarget = null;
+ if (!interceptHover && action != MotionEvent.ACTION_HOVER_EXIT) {
final float x = event.getX();
final float y = event.getY();
-
- if (interceptHover
- || !isTransformedTouchPointInView(x, y, mHoveredChild, null)) {
- // Pointer exited the child.
- // Send it a hover exit with only the most recent coordinates. We could
- // try to find the exact point in history when the pointer left the view
- // but it is not worth the effort.
- eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
- eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
- handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, mHoveredChild);
- eventNoHistory.setAction(action);
- mHoveredChild = null;
- } else {
- // Pointer is still within the child.
- //noinspection ConstantConditions
- handled |= dispatchTransformedGenericPointerEvent(event, mHoveredChild);
- }
- }
-
- // Find a new hovered child if needed.
- if (!interceptHover && mHoveredChild == null
- && (action == MotionEvent.ACTION_HOVER_ENTER
- || action == MotionEvent.ACTION_HOVER_MOVE)) {
final int childrenCount = mChildrenCount;
if (childrenCount != 0) {
final View[] children = mChildren;
- final float x = event.getX();
- final float y = event.getY();
-
+ HoverTarget lastHoverTarget = null;
for (int i = childrenCount - 1; i >= 0; i--) {
final View child = children[i];
if (!canViewReceivePointerEvents(child)
@@ -1279,24 +1264,140 @@
continue;
}
- // Found the hovered child.
- mHoveredChild = child;
- if (action == MotionEvent.ACTION_HOVER_MOVE) {
- // Pointer was moving within the view group and entered the child.
- // Send it a hover enter and hover move with only the most recent
- // coordinates. We could try to find the exact point in history when
- // the pointer entered the view but it is not worth the effort.
- eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
- eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
- handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
- eventNoHistory.setAction(action);
+ // Obtain a hover target for this child. Dequeue it from the
+ // old hover target list if the child was previously hovered.
+ HoverTarget hoverTarget = firstOldHoverTarget;
+ final boolean wasHovered;
+ for (HoverTarget predecessor = null; ;) {
+ if (hoverTarget == null) {
+ hoverTarget = HoverTarget.obtain(child);
+ wasHovered = false;
+ break;
+ }
- handled |= dispatchTransformedGenericPointerEvent(eventNoHistory, child);
- } else { /* must be ACTION_HOVER_ENTER */
- // Pointer entered the child.
- handled |= dispatchTransformedGenericPointerEvent(event, child);
+ if (hoverTarget.child == child) {
+ if (predecessor != null) {
+ predecessor.next = hoverTarget.next;
+ } else {
+ firstOldHoverTarget = hoverTarget.next;
+ }
+ hoverTarget.next = null;
+ wasHovered = true;
+ break;
+ }
+
+ predecessor = hoverTarget;
+ hoverTarget = hoverTarget.next;
}
- break;
+
+ // Enqueue the hover target onto the new hover target list.
+ if (lastHoverTarget != null) {
+ lastHoverTarget.next = hoverTarget;
+ } else {
+ lastHoverTarget = hoverTarget;
+ mFirstHoverTarget = hoverTarget;
+ }
+
+ // Dispatch the event to the child.
+ if (action == MotionEvent.ACTION_HOVER_ENTER) {
+ if (!wasHovered) {
+ // Send the enter as is.
+ handled |= dispatchTransformedGenericPointerEvent(
+ event, child); // enter
+ }
+ } else if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ if (!wasHovered) {
+ // Synthesize an enter from a move.
+ eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
+ handled |= dispatchTransformedGenericPointerEvent(
+ eventNoHistory, child); // enter
+ eventNoHistory.setAction(action);
+
+ handled |= dispatchTransformedGenericPointerEvent(
+ eventNoHistory, child); // move
+ } else {
+ // Send the move as is.
+ handled |= dispatchTransformedGenericPointerEvent(event, child);
+ }
+ }
+ if (handled) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Send exit events to all previously hovered children that are no longer hovered.
+ while (firstOldHoverTarget != null) {
+ final View child = firstOldHoverTarget.child;
+
+ // Exit the old hovered child.
+ if (action == MotionEvent.ACTION_HOVER_EXIT) {
+ // Send the exit as is.
+ handled |= dispatchTransformedGenericPointerEvent(
+ event, child); // exit
+ } else {
+ // Synthesize an exit from a move or enter.
+ // Ignore the result because hover focus has moved to a different view.
+ if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ dispatchTransformedGenericPointerEvent(
+ event, child); // move
+ }
+ eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
+ dispatchTransformedGenericPointerEvent(
+ eventNoHistory, child); // exit
+ eventNoHistory.setAction(action);
+ }
+
+ final HoverTarget nextOldHoverTarget = firstOldHoverTarget.next;
+ firstOldHoverTarget.recycle();
+ firstOldHoverTarget = nextOldHoverTarget;
+ }
+
+ // Send events to the view group itself if no children have handled it.
+ boolean newHoveredSelf = !handled;
+ if (newHoveredSelf == mHoveredSelf) {
+ if (newHoveredSelf) {
+ // Send event to the view group as before.
+ handled |= super.dispatchHoverEvent(event);
+ }
+ } else {
+ if (mHoveredSelf) {
+ // Exit the view group.
+ if (action == MotionEvent.ACTION_HOVER_EXIT) {
+ // Send the exit as is.
+ handled |= super.dispatchHoverEvent(event); // exit
+ } else {
+ // Synthesize an exit from a move or enter.
+ // Ignore the result because hover focus is moving to a different view.
+ if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ super.dispatchHoverEvent(event); // move
+ }
+ eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
+ super.dispatchHoverEvent(eventNoHistory); // exit
+ eventNoHistory.setAction(action);
+ }
+ mHoveredSelf = false;
+ }
+
+ if (newHoveredSelf) {
+ // Enter the view group.
+ if (action == MotionEvent.ACTION_HOVER_ENTER) {
+ // Send the enter as is.
+ handled |= super.dispatchHoverEvent(event); // enter
+ mHoveredSelf = true;
+ } else if (action == MotionEvent.ACTION_HOVER_MOVE) {
+ // Synthesize an enter from a move.
+ eventNoHistory = obtainMotionEventNoHistoryOrSelf(eventNoHistory);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
+ handled |= super.dispatchHoverEvent(eventNoHistory); // enter
+ eventNoHistory.setAction(action);
+
+ handled |= super.dispatchHoverEvent(eventNoHistory); // move
+ mHoveredSelf = true;
}
}
}
@@ -1306,25 +1407,55 @@
eventNoHistory.recycle();
}
- // Send hover exit to the view group. If there was a child, we will already have
- // sent the hover exit to it.
- if (action == MotionEvent.ACTION_HOVER_EXIT) {
- handled |= super.dispatchHoverEvent(event);
- }
-
// Done.
return handled;
}
+ /** @hide */
@Override
- public boolean onHoverEvent(MotionEvent event) {
- // Handle the event only if leaf. This guarantees that
- // the leafs (or any custom class that returns true from
- // this method) will get a change to process the hover.
- //noinspection SimplifiableIfStatement
- if (getChildCount() == 0) {
- return super.onHoverEvent(event);
- }
+ protected boolean hasHoveredChild() {
+ return mFirstHoverTarget != null;
+ }
+
+ /**
+ * Implement this method to intercept hover events before they are handled
+ * by child views.
+ * <p>
+ * This method is called before dispatching a hover event to a child of
+ * the view group or to the view group's own {@link #onHoverEvent} to allow
+ * the view group a chance to intercept the hover event.
+ * This method can also be used to watch all pointer motions that occur within
+ * the bounds of the view group even when the pointer is hovering over
+ * a child of the view group rather than over the view group itself.
+ * </p><p>
+ * The view group can prevent its children from receiving hover events by
+ * implementing this method and returning <code>true</code> to indicate
+ * that it would like to intercept hover events. The view group must
+ * continuously return <code>true</code> from {@link #onInterceptHoverEvent}
+ * for as long as it wishes to continue intercepting hover events from
+ * its children.
+ * </p><p>
+ * Interception preserves the invariant that at most one view can be
+ * hovered at a time by transferring hover focus from the currently hovered
+ * child to the view group or vice-versa as needed.
+ * </p><p>
+ * If this method returns <code>true</code> and a child is already hovered, then the
+ * child view will first receive a hover exit event and then the view group
+ * itself will receive a hover enter event in {@link #onHoverEvent}.
+ * Likewise, if this method had previously returned <code>true</code> to intercept hover
+ * events and instead returns <code>false</code> while the pointer is hovering
+ * within the bounds of one of a child, then the view group will first receive a
+ * hover exit event in {@link #onHoverEvent} and then the hovered child will
+ * receive a hover enter event.
+ * </p><p>
+ * The default implementation always returns false.
+ * </p>
+ *
+ * @param event The motion event that describes the hover.
+ * @return True if the view group would like to intercept the hover event
+ * and prevent its children from receiving it.
+ */
+ public boolean onInterceptHoverEvent(MotionEvent event) {
return false;
}
@@ -1335,7 +1466,9 @@
return MotionEvent.obtainNoHistory(event);
}
- /** @hide */
+ /**
+ * {@inheritDoc}
+ */
@Override
protected boolean dispatchGenericPointerEvent(MotionEvent event) {
// Send the event to the child under the pointer.
@@ -1362,7 +1495,9 @@
return super.dispatchGenericPointerEvent(event);
}
- /** @hide */
+ /**
+ * {@inheritDoc}
+ */
@Override
protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
// Send the event to the focused child or to this view group if it has focus.
@@ -1611,6 +1746,7 @@
final long now = SystemClock.uptimeMillis();
event = MotionEvent.obtain(now, now,
MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
syntheticEvent = true;
}
@@ -3337,10 +3473,6 @@
mTransition.removeChild(this, view);
}
- if (view == mHoveredChild) {
- mHoveredChild = null;
- }
-
boolean clearChildFocus = false;
if (view == mFocused) {
view.clearFocusForRemoval();
@@ -3404,7 +3536,6 @@
final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener;
final boolean notifyListener = onHierarchyChangeListener != null;
final View focused = mFocused;
- final View hoveredChild = mHoveredChild;
final boolean detach = mAttachInfo != null;
View clearChildFocus = null;
@@ -3418,10 +3549,6 @@
mTransition.removeChild(this, view);
}
- if (view == hoveredChild) {
- mHoveredChild = null;
- }
-
if (view == focused) {
view.clearFocusForRemoval();
clearChildFocus = view;
@@ -3479,7 +3606,6 @@
final OnHierarchyChangeListener listener = mOnHierarchyChangeListener;
final boolean notify = listener != null;
final View focused = mFocused;
- final View hoveredChild = mHoveredChild;
final boolean detach = mAttachInfo != null;
View clearChildFocus = null;
@@ -3492,10 +3618,6 @@
mTransition.removeChild(this, view);
}
- if (view == hoveredChild) {
- mHoveredChild = null;
- }
-
if (view == focused) {
view.clearFocusForRemoval();
clearChildFocus = view;
@@ -3757,8 +3879,10 @@
if (!childMatrix.isIdentity()) {
RectF boundingRect = attachInfo.mTmpTransformRect;
boundingRect.set(dirty);
+ //boundingRect.inset(-0.5f, -0.5f);
childMatrix.mapRect(boundingRect);
- dirty.set((int) boundingRect.left, (int) boundingRect.top,
+ dirty.set((int) (boundingRect.left - 0.5f),
+ (int) (boundingRect.top - 0.5f),
(int) (boundingRect.right + 0.5f),
(int) (boundingRect.bottom + 0.5f));
}
@@ -4875,6 +4999,65 @@
viewAncestor.requestTransitionStart(transition);
}
+ @Override
+ protected void resetLayoutDirectionResolution() {
+ super.resetLayoutDirectionResolution();
+
+ // Take care of resetting the children resolution too
+ final int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getLayoutDirection() == LAYOUT_DIRECTION_INHERIT) {
+ child.resetLayoutDirectionResolution();
+ }
+ }
+ }
+
+ /**
+ * This method will be called during text direction resolution (text direction resolution
+ * inheritance)
+ */
+ @Override
+ protected void resolveTextDirection() {
+ int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+ switch(mTextDirection) {
+ default:
+ case TEXT_DIRECTION_INHERIT:
+ // Try to the text direction from the parent layout
+ if (mParent != null && mParent instanceof ViewGroup) {
+ resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+ } else {
+ // We reached the top of the View hierarchy, so get the direction from
+ // the Locale
+ resolvedTextDirection = isLayoutDirectionRtl(Locale.getDefault()) ?
+ TEXT_DIRECTION_RTL : TEXT_DIRECTION_LTR;
+ }
+ break;
+ // Pass down the hierarchy the following text direction values
+ case TEXT_DIRECTION_FIRST_STRONG:
+ case TEXT_DIRECTION_ANY_RTL:
+ case TEXT_DIRECTION_LTR:
+ case TEXT_DIRECTION_RTL:
+ resolvedTextDirection = mTextDirection;
+ break;
+ }
+ mResolvedTextDirection = resolvedTextDirection;
+ }
+
+ @Override
+ protected void resetResolvedTextDirection() {
+ super.resetResolvedTextDirection();
+
+ // Take care of resetting the children resolution too
+ final int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getTextDirection() == TEXT_DIRECTION_INHERIT) {
+ child.resetResolvedTextDirection();
+ }
+ }
+ }
+
/**
* Return true if the pressed state should be delayed for children or descendants of this
* ViewGroup. Generally, this should be done for containers that can scroll, such as a List.
@@ -5035,6 +5218,21 @@
}
/**
+ * Resolve layout parameters depending on the layout direction. Subclasses that care about
+ * layoutDirection changes should override this method. The default implementation does
+ * nothing.
+ *
+ * @param layoutDirection the direction of the layout
+ *
+ * {@link View#LAYOUT_DIRECTION_LTR}
+ * {@link View#LAYOUT_DIRECTION_RTL}
+ *
+ * @hide
+ */
+ protected void resolveWithDirection(int layoutDirection) {
+ }
+
+ /**
* Returns a String representation of this set of layout parameters.
*
* @param output the String to prepend to the internal representation
@@ -5075,30 +5273,56 @@
*/
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
/**
- * The left margin in pixels of the child.
+ * The left margin in pixels of the child. Whenever this value is changed, a call to
+ * {@link android.view.View#requestLayout()} needs to be done.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int leftMargin;
/**
- * The top margin in pixels of the child.
+ * The top margin in pixels of the child. Whenever this value is changed, a call to
+ * {@link android.view.View#requestLayout()} needs to be done.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int topMargin;
/**
- * The right margin in pixels of the child.
+ * The right margin in pixels of the child. Whenever this value is changed, a call to
+ * {@link android.view.View#requestLayout()} needs to be done.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int rightMargin;
/**
- * The bottom margin in pixels of the child.
+ * The bottom margin in pixels of the child. Whenever this value is changed, a call to
+ * {@link android.view.View#requestLayout()} needs to be done.
*/
@ViewDebug.ExportedProperty(category = "layout")
public int bottomMargin;
/**
+ * The start margin in pixels of the child.
+ *
+ * @hide
+ *
+ */
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int startMargin = DEFAULT_RELATIVE;
+
+ /**
+ * The end margin in pixels of the child.
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "layout")
+ protected int endMargin = DEFAULT_RELATIVE;
+
+ /**
+ * The default start and end margin.
+ */
+ static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
+
+ /**
* Creates a new set of layout parameters. The values are extracted from
* the supplied attributes set and context.
*
@@ -5130,6 +5354,10 @@
R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
bottomMargin = a.getDimensionPixelSize(
R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
+ startMargin = a.getDimensionPixelSize(
+ R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_RELATIVE);
+ endMargin = a.getDimensionPixelSize(
+ R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
}
a.recycle();
@@ -5155,6 +5383,8 @@
this.topMargin = source.topMargin;
this.rightMargin = source.rightMargin;
this.bottomMargin = source.bottomMargin;
+ this.startMargin = source.startMargin;
+ this.endMargin = source.endMargin;
}
/**
@@ -5165,7 +5395,9 @@
}
/**
- * Sets the margins, in pixels.
+ * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs
+ * to be done so that the new margins are taken into account. Left and right margins may be
+ * overriden by {@link android.view.View#requestLayout()} depending on layout direction.
*
* @param left the left margin size
* @param top the top margin size
@@ -5183,6 +5415,92 @@
rightMargin = right;
bottomMargin = bottom;
}
+
+ /**
+ * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()}
+ * needs to be done so that the new relative margins are taken into account. Left and right
+ * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout
+ * direction.
+ *
+ * @param start the start margin size
+ * @param top the top margin size
+ * @param end the right margin size
+ * @param bottom the bottom margin size
+ *
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
+ *
+ * @hide
+ */
+ public void setMarginsRelative(int start, int top, int end, int bottom) {
+ startMargin = start;
+ topMargin = top;
+ endMargin = end;
+ bottomMargin = bottom;
+ }
+
+ /**
+ * Returns the start margin in pixels.
+ *
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+ *
+ * @return the start margin in pixels.
+ *
+ * @hide
+ */
+ public int getMarginStart() {
+ return startMargin;
+ }
+
+ /**
+ * Returns the end margin in pixels.
+ *
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+ *
+ * @return the end margin in pixels.
+ *
+ * @hide
+ */
+ public int getMarginEnd() {
+ return endMargin;
+ }
+
+ /**
+ * Check if margins are relative.
+ *
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
+ * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
+ *
+ * @return true if either marginStart or marginEnd has been set
+ *
+ * @hide
+ */
+ public boolean isMarginRelative() {
+ return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
+ }
+
+ /**
+ * This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
+ * maybe overriden depending on layout direction.
+ *
+ * @hide
+ */
+ @Override
+ protected void resolveWithDirection(int layoutDirection) {
+ switch(layoutDirection) {
+ case View.LAYOUT_DIRECTION_RTL:
+ leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
+ rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+ break;
+ case View.LAYOUT_DIRECTION_LTR:
+ default:
+ leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
+ rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+ break;
+ }
+ }
}
/* Describes a touched view and the ids of the pointers that it has captured.
@@ -5242,4 +5560,50 @@
}
}
}
+
+ /* Describes a hovered view. */
+ private static final class HoverTarget {
+ private static final int MAX_RECYCLED = 32;
+ private static final Object sRecycleLock = new Object();
+ private static HoverTarget sRecycleBin;
+ private static int sRecycledCount;
+
+ // The hovered child view.
+ public View child;
+
+ // The next target in the target list.
+ public HoverTarget next;
+
+ private HoverTarget() {
+ }
+
+ public static HoverTarget obtain(View child) {
+ final HoverTarget target;
+ synchronized (sRecycleLock) {
+ if (sRecycleBin == null) {
+ target = new HoverTarget();
+ } else {
+ target = sRecycleBin;
+ sRecycleBin = target.next;
+ sRecycledCount--;
+ target.next = null;
+ }
+ }
+ target.child = child;
+ return target;
+ }
+
+ public void recycle() {
+ synchronized (sRecycleLock) {
+ if (sRecycledCount < MAX_RECYCLED) {
+ next = sRecycleBin;
+ sRecycleBin = this;
+ sRecycledCount += 1;
+ } else {
+ next = null;
+ }
+ child = null;
+ }
+ }
+ }
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 5ef7763..ac86769 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -25,150 +25,239 @@
import java.util.List;
/**
+ * <p>
* This class represents accessibility events that are sent by the system when
* something notable happens in the user interface. For example, when a
* {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
+ * </p>
* <p>
* An accessibility event is fired by an individual view which populates the event with
- * a record for its state and requests from its parent to send the event to interested
- * parties. The parent can optionally add a record for itself before dispatching a similar
- * request to its parent. A parent can also choose not to respect the request for sending
- * an event. The accessibility event is sent by the topmost view in the view tree.
- * Therefore, an {@link android.accessibilityservice.AccessibilityService} can explore
- * all records in an accessibility event to obtain more information about the context
- * in which the event was fired.
+ * data for its state and requests from its parent to send the event to interested
+ * parties. The parent can optionally add an {@link AccessibilityRecord} for itself before
+ * dispatching a similar request to its parent. A parent can also choose not to respect the
+ * request for sending an event. The accessibility event is sent by the topmost view in the
+ * view tree. Therefore, an {@link android.accessibilityservice.AccessibilityService} can
+ * explore all records in an accessibility event to obtain more information about the
+ * context in which the event was fired.
+ * </p>
* <p>
- * A client can add, remove, and modify records. The getters and setters for individual
- * properties operate on the current record which can be explicitly set by the client. By
- * default current is the first record. Thus, querying a record would require setting
- * it as the current one and interacting with the property getters and setters.
+ * The main purpose of an accessibility event is to expose enough information for an
+ * {@link android.accessibilityservice.AccessibilityService} to provide meaningful feedback
+ * to the user. Sometimes however, an accessibility service may need more contextual
+ * information then the one in the event pay-load. In such cases the service can obtain
+ * the event source which is an {@link AccessibilityNodeInfo} (snapshot of a View state)
+ * which can be used for exploring the window content. Note that the privilege for accessing
+ * an event's source, thus the window content, has to be explicitly requested. For more
+ * details refer to {@link android.accessibilityservice.AccessibilityService}. If an
+ * accessibility service has not requested to retrieve the window content the event will
+ * not contain reference to its source. Also for events of type
+ * {@link #TYPE_NOTIFICATION_STATE_CHANGED} the source is never available.
+ * </p>
* <p>
* This class represents various semantically different accessibility event
- * types. Each event type has associated a set of related properties. In other
+ * types. Each event type has an associated set of related properties. In other
* words, each event type is characterized via a subset of the properties exposed
* by this class. For each event type there is a corresponding constant defined
- * in this class. Since some event types are semantically close there are mask
- * constants that group them together. Follows a specification of the event
- * types and their associated properties:
+ * in this class. Follows a specification of the event types and their associated properties:
+ * </p>
* <p>
- * <b>VIEW TYPES</b> <br>
+ * <b>VIEW TYPES</b></br>
+ * </p>
* <p>
* <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
- * Type:{@link #TYPE_VIEW_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.</br>
+ * <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
+ * </p>
* <p>
* <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
- * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
- * Type:{@link #TYPE_VIEW_LONG_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc </br>
+ * <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
+ * </p>
* <p>
* <b>View selected</b> - represents the event of selecting an item usually in
- * the context of an {@link android.widget.AdapterView}. <br>
- * Type: {@link #TYPE_VIEW_SELECTED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * the context of an {@link android.widget.AdapterView}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getItemCount()} - The number of selectable items of the source.</li>
+ * <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
+ * </ul>
+ * </p>
* <p>
* <b>View focused</b> - represents the event of focusing a
- * {@link android.view.View}. <br>
- * Type: {@link #TYPE_VIEW_FOCUSED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * {@link android.view.View}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getItemCount()} - The number of focusable items on the screen.</li>
+ * <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
+ * </ul>
+ * </p>
* <p>
* <b>View text changed</b> - represents the event of changing the text of an
- * {@link android.widget.EditText}. <br>
- * Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()},
- * {@link #getFromIndex()},
- * {@link #getAddedCount()},
- * {@link #getRemovedCount()},
- * {@link #getBeforeText()}
+ * {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getFromIndex()} - The text change start index.</li>
+ * <li>{@link #getAddedCount()} - The number of added characters.</li>
+ * <li>{@link #getRemovedCount()} - The number of removed characters.</li>
+ * <li>{@link #getBeforeText()} - The text of the source before the change.</li>
+ * </ul>
+ * </p>
* <p>
- * <b>TRANSITION TYPES</b> <br>
+ * <b>View text selection changed</b> - represents the event of changing the text
+ * selection of an {@link android.widget.EditText}.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #getFromIndex()} - The selection start index.</li>
+ * <li>{@link #getToIndex()} - The selection end index.</li>
+ * <li>{@link #getItemCount()} - The length of the source text.</li>
+ * </ul>
+ * </p>
* <p>
+ * <b>View scrolled</b> - represents the event of scrolling a view. If
+ * the source is a descendant of {@link android.widget.AdapterView} the
+ * scroll is reported in terms of visible items - the first visible item,
+ * the last visible item, and the total items - because the the source
+ * is unaware if its pixel size since its adapter is responsible for
+ * creating views. In all other cases the scroll is reported as the current
+ * scroll on the X and Y axis respectively plus the height of the source in
+ * pixels.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getScrollX()} - The horizontal offset of the source
+ * (without descendants of AdapterView)).</li>
+ * <li>{@link #getScrollY()} - The vertical offset of the source
+ * (without descendants of AdapterView)).</li>
+ * <li>{@link #getFromIndex()} - The index of the first visible item of the source
+ * (for descendants of AdapterView).</li>
+ * <li>{@link #getToIndex()} - The index of the last visible item of the source
+ * (for descendants of AdapterView).</li>
+ * <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
+ * or the height of the source in pixels (all other cases).</li>
+ * </ul>
+ * </p>
+ * <p>
+ * <b>TRANSITION TYPES</b></br>
+ * </p>
* <b>Window state changed</b> - represents the event of opening a
* {@link android.widget.PopupWindow}, {@link android.view.Menu},
- * {@link android.app.Dialog}, etc. <br>
- * Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * {@link android.app.Dialog}, etc.</br>
+ * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * </ul>
+ * </p>
* <p>
* <b>Window content changed</b> - represents the event of change in the
* content of a window. This change can be adding/removing view, changing
- * a view size, etc.<br>
- * Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * a view size, etc.</br>
* <p>
- * <b>NOTIFICATION TYPES</b> <br>
+ * <strong>Note:</strong> This event is fired only for the window source of the
+ * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED})
+ * and its purpose is to notify clients that the content of the user interaction
+ * window has changed.
+ * </p>
+ * <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * </ul>
* <p>
- * <b>Notification state changed</b> - represents the event showing/hiding
+ * <b>NOTIFICATION TYPES</b></br>
+ * <p>
+ * <b>Notification state changed</b> - represents the event showing
* {@link android.app.Notification}.
- * Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
- * {@link #getParcelableData()}
+ * <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * </ul>
+ * </p>
* <p>
* <b>Security note</b>
* <p>
- * Since an event contains the text of its source privacy can be compromised by leaking of
+ * Since an event contains the text of its source privacy can be compromised by leaking
* sensitive information such as passwords. To address this issue any event fired in response
* to manipulation of a PASSWORD field does NOT CONTAIN the text of the password.
*
* @see android.view.accessibility.AccessibilityManager
* @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityNodeInfo
*/
public final class AccessibilityEvent extends AccessibilityRecord implements Parcelable {
private static final boolean DEBUG = false;
@@ -222,13 +311,13 @@
public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
/**
- * Represents the event of opening/closing a {@link android.widget.PopupWindow},
+ * Represents the event of opening a {@link android.widget.PopupWindow},
* {@link android.view.Menu}, {@link android.app.Dialog}, etc.
*/
public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
/**
- * Represents the event showing/hiding a {@link android.app.Notification}.
+ * Represents the event showing a {@link android.app.Notification}.
*/
public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
@@ -258,6 +347,16 @@
public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
/**
+ * Represents the event of scrolling a view.
+ */
+ public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+
+ /**
+ * Represents the event of changing the selection in an {@link android.widget.EditText}.
+ */
+ public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -267,6 +366,13 @@
* @see #TYPE_VIEW_TEXT_CHANGED
* @see #TYPE_WINDOW_STATE_CHANGED
* @see #TYPE_NOTIFICATION_STATE_CHANGED
+ * @see #TYPE_VIEW_HOVER_ENTER
+ * @see #TYPE_VIEW_HOVER_EXIT
+ * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
+ * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
+ * @see #TYPE_WINDOW_CONTENT_CHANGED
+ * @see #TYPE_VIEW_SCROLLED
+ * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
*/
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
@@ -359,10 +465,10 @@
}
/**
- * Gets the records at a given index.
+ * Gets the record at a given index.
*
* @param index The index.
- * @return The records at the specified index.
+ * @return The record at the specified index.
*/
public AccessibilityRecord getRecord(int index) {
return mRecords.get(index);
@@ -433,7 +539,7 @@
/**
* Returns a cached instance if such is available or a new one is
- * instantiated with type property set.
+ * instantiated with its type property set.
*
* @param eventType The event type.
* @return An instance.
@@ -446,7 +552,7 @@
/**
* Returns a cached instance if such is available or a new one is
- * instantiated with type property set.
+ * initialized with from the given <code>event</code>.
*
* @param event The other event.
* @return An instance.
@@ -486,9 +592,10 @@
}
/**
- * Return an instance back to be reused.
+ * Recycles an instance back to be reused.
* <p>
- * <b>Note: You must not touch the object after calling this function.</b>
+ * <b>Note: You must not touch the object after calling this function.</b>
+ * </p>
*
* @throws IllegalStateException If the event is already recycled.
*/
@@ -545,9 +652,9 @@
final int recordCount = parcel.readInt();
for (int i = 0; i < recordCount; i++) {
AccessibilityRecord record = AccessibilityRecord.obtain();
- readAccessibilityRecordFromParcel(record, parcel);
// Do this to write the connection only once.
record.setConnection(mConnection);
+ readAccessibilityRecordFromParcel(record, parcel);
mRecords.add(record);
}
}
@@ -564,6 +671,9 @@
record.mCurrentItemIndex = parcel.readInt();
record.mItemCount = parcel.readInt();
record.mFromIndex = parcel.readInt();
+ record.mToIndex = parcel.readInt();
+ record.mScrollX = parcel.readInt();
+ record.mScrollY = parcel.readInt();
record.mAddedCount = parcel.readInt();
record.mRemovedCount = parcel.readInt();
record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
@@ -613,6 +723,9 @@
parcel.writeInt(record.mCurrentItemIndex);
parcel.writeInt(record.mItemCount);
parcel.writeInt(record.mFromIndex);
+ parcel.writeInt(record.mToIndex);
+ parcel.writeInt(record.mScrollX);
+ parcel.writeInt(record.mScrollY);
parcel.writeInt(record.mAddedCount);
parcel.writeInt(record.mRemovedCount);
TextUtils.writeToParcel(record.mClassName, parcel, flags);
@@ -635,7 +748,7 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append("; EventType: ").append(eventTypeToString(mEventType));
+ builder.append("EventType: ").append(eventTypeToString(mEventType));
builder.append("; EventTime: ").append(mEventTime);
builder.append("; PackageName: ").append(mPackageName);
builder.append(super.toString());
@@ -657,8 +770,12 @@
builder.append("; IsPassword: " + record.isPassword());
builder.append("; IsChecked: " + record.isChecked());
builder.append("; IsFullScreen: " + record.isFullScreen());
+ builder.append("; Scrollable: " + record.isScrollable());
builder.append("; BeforeText: " + record.mBeforeText);
builder.append("; FromIndex: " + record.mFromIndex);
+ builder.append("; ToIndex: " + record.mToIndex);
+ builder.append("; ScrollX: " + record.mScrollX);
+ builder.append("; ScrollY: " + record.mScrollY);
builder.append("; AddedCount: " + record.mAddedCount);
builder.append("; RemovedCount: " + record.mRemovedCount);
builder.append("; ParcelableData: " + record.mParcelableData);
@@ -675,11 +792,11 @@
* Returns the string representation of an event type. For example,
* {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
*
- * @param feedbackType The event type
+ * @param eventType The event type
* @return The string representation.
*/
- public static String eventTypeToString(int feedbackType) {
- switch (feedbackType) {
+ public static String eventTypeToString(int eventType) {
+ switch (eventType) {
case TYPE_VIEW_CLICKED:
return "TYPE_VIEW_CLICKED";
case TYPE_VIEW_LONG_CLICKED:
@@ -704,6 +821,10 @@
return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
case TYPE_WINDOW_CONTENT_CHANGED:
return "TYPE_WINDOW_CONTENT_CHANGED";
+ case TYPE_VIEW_TEXT_SELECTION_CHANGED:
+ return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
+ case TYPE_VIEW_SCROLLED:
+ return "TYPE_VIEW_SCROLLED";
default:
return null;
}
diff --git a/core/java/android/view/accessibility/AccessibilityEventSource.java b/core/java/android/view/accessibility/AccessibilityEventSource.java
index 3d70959..f11880b 100644
--- a/core/java/android/view/accessibility/AccessibilityEventSource.java
+++ b/core/java/android/view/accessibility/AccessibilityEventSource.java
@@ -24,11 +24,12 @@
/**
* Handles the request for sending an {@link AccessibilityEvent} given
* the event type. The method must first check if accessibility is on
- * via calling {@link AccessibilityManager#isEnabled()}, obtain
- * an {@link AccessibilityEvent} from the event pool through calling
- * {@link AccessibilityEvent#obtain(int)}, populate the event, and
- * send it for dispatch via calling
- * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)}.
+ * via calling {@link AccessibilityManager#isEnabled() AccessibilityManager.isEnabled()},
+ * obtain an {@link AccessibilityEvent} from the event pool through calling
+ * {@link AccessibilityEvent#obtain(int) AccessibilityEvent.obtain(int)}, populate the
+ * event, and send it for dispatch via calling
+ * {@link AccessibilityManager#sendAccessibilityEvent(AccessibilityEvent)
+ * AccessibilityManager.sendAccessibilityEvent(AccessibilityEvent)}.
*
* @see AccessibilityEvent
* @see AccessibilityManager
@@ -41,7 +42,8 @@
* Handles the request for sending an {@link AccessibilityEvent}. The
* method does not guarantee to check if accessibility is on before
* sending the event for dispatch. It is responsibility of the caller
- * to do the check via calling {@link AccessibilityManager#isEnabled()}.
+ * to do the check via calling {@link AccessibilityManager#isEnabled()
+ * AccessibilityManager.isEnabled()}.
*
* @see AccessibilityEvent
* @see AccessibilityManager
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index eece64a..314b7ca 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -37,16 +37,30 @@
import java.util.concurrent.CopyOnWriteArrayList;
/**
- * System level service that serves as an event dispatch for {@link AccessibilityEvent}s.
- * Such events are generated when something notable happens in the user interface,
+ * System level service that serves as an event dispatch for {@link AccessibilityEvent}s,
+ * and provides facilities for querying the accessibility state of the system.
+ * Accessibility events are generated when something notable happens in the user interface,
* for example an {@link android.app.Activity} starts, the focus or selection of a
* {@link android.view.View} changes etc. Parties interested in handling accessibility
* events implement and register an accessibility service which extends
* {@link android.accessibilityservice.AccessibilityService}.
+ * <p>
+ * To obtain a handle to the accessibility manager do the following:
+ * </p>
+ * <p>
+ * <code>
+ * <pre>
+ * AccessibilityManager accessibilityManager =
+ * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ * </pre>
+ * </code>
+ * </p>
*
* @see AccessibilityEvent
+ * @see AccessibilityNodeInfo
* @see android.accessibilityservice.AccessibilityService
- * @see android.content.Context#getSystemService
+ * @see Context#getSystemService
+ * @see Context#ACCESSIBILITY_SERVICE
*/
public final class AccessibilityManager {
private static final boolean DEBUG = false;
@@ -72,10 +86,11 @@
* Listener for the accessibility state.
*/
public interface AccessibilityStateChangeListener {
+
/**
* Called back on change in the accessibility state.
*
- * @param enabled
+ * @param enabled Whether accessibility is enabled.
*/
public void onAccessibilityStateChanged(boolean enabled);
}
@@ -142,9 +157,9 @@
}
/**
- * Returns if the {@link AccessibilityManager} is enabled.
+ * Returns if the accessibility in the system is enabled.
*
- * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
+ * @return True if accessibility is enabled, false otherwise.
*/
public boolean isEnabled() {
synchronized (mHandler) {
@@ -161,17 +176,15 @@
* @hide
*/
public IAccessibilityManagerClient getClient() {
- return (IAccessibilityManagerClient) mClient.asBinder();
+ return (IAccessibilityManagerClient) mClient.asBinder();
}
/**
- * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not
- * enabled the call is a NOOP.
+ * Sends an {@link AccessibilityEvent}.
*
- * @param event The {@link AccessibilityEvent}.
+ * @param event The event to send.
*
- * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent}
- * while accessibility is not enabled.
+ * @throws IllegalStateException if accessibility is not enabled.
*/
public void sendAccessibilityEvent(AccessibilityEvent event) {
if (!mIsEnabled) {
@@ -199,7 +212,7 @@
}
/**
- * Requests interruption of the accessibility feedback from all accessibility services.
+ * Requests feedback interruption from all accessibility services.
*/
public void interrupt() {
if (!mIsEnabled) {
@@ -256,13 +269,20 @@
* Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
* for a given feedback type.
*
- * @param feedbackType The feedback type (can be bitwise or of multiple types).
+ * @param feedbackTypeFlags The feedback type flags.
* @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
+ *
+ * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
+ * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
+ * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
+ * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
+ * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
*/
- public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+ public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
+ int feedbackTypeFlags) {
List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getEnabledAccessibilityServiceList(feedbackType);
+ services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
if (DEBUG) {
Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
}
@@ -273,7 +293,8 @@
}
/**
- * Registers an {@link AccessibilityStateChangeListener}.
+ * Registers an {@link AccessibilityStateChangeListener} for changes in
+ * the global accessibility state of the system.
*
* @param listener The listener.
* @return True if successfully registered.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 18ef38a..031c6ae 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -22,7 +22,6 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.text.TextUtils;
-import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.View;
@@ -30,12 +29,26 @@
import java.util.List;
/**
- * This class represents a node of the screen content. From the point of
- * view of an accessibility service the screen content is presented as tree
- * of accessibility nodes.
+ * This class represents a node of the window content as well as actions that
+ * can be requested from its source. From the point of view of an
+ * {@link android.accessibilityservice.AccessibilityService} a window content is
+ * presented as tree of accessibility node info which may or may not map one-to-one
+ * to the view hierarchy. In other words, a custom view is free to report itself as
+ * a tree of accessibility node info.
+ * </p>
+ * <p>
+ * Once an accessibility node info is delivered to an accessibility service it is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * Please refer to {@link android.accessibilityservice.AccessibilityService} for
+ * details about how to obtain a handle to window content as a tree of accessibility
+ * node info as well as familiarizing with the security model.
+ * </p>
*
- * TODO(svertoslavganov): Update the documentation, add sample, and describe
- * the security policy.
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityEvent
+ * @see AccessibilityManager
*/
public class AccessibilityNodeInfo implements Parcelable {
@@ -83,8 +96,7 @@
private static final int PROPERTY_PASSWORD = 0x00000100;
- // Readable representations - lazily initialized.
- private static SparseArray<String> sActionSymbolicNames;
+ private static final int PROPERTY_SCROLLABLE = 0x00000200;
// Housekeeping.
private static final int MAX_POOL_SIZE = 50;
@@ -152,12 +164,11 @@
/**
* Get the child at given index.
* <p>
- * <strong>
- * It is a client responsibility to recycle the received info by
- * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
- * of multiple instances.
- * </strong>
+ * <strong>Note:</strong> It is a client responsibility to recycle the
+ * received info by calling {@link AccessibilityNodeInfo#recycle()}
+ * to avoid creating of multiple instances.
* </p>
+ *
* @param index The child index.
* @return The child node.
*
@@ -182,9 +193,11 @@
/**
* Adds a child.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param child The child.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -213,9 +226,11 @@
/**
* Adds an action that can be performed on the node.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param action The action.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -228,9 +243,10 @@
/**
* Performs an action on the node.
* <p>
- * Note: An action can be performed only if the request is made
+ * <strong>Note:</strong> An action can be performed only if the request is made
* from an {@link android.accessibilityservice.AccessibilityService}.
* </p>
+ *
* @param action The action to perform.
* @return True if the action was performed.
*
@@ -252,7 +268,13 @@
/**
* Finds {@link AccessibilityNodeInfo}s by text. The match is case
- * insensitive containment.
+ * insensitive containment. The search is relative to this info i.e.
+ * this info is the root of the traversed tree.
+ * <p>
+ * <strong>Note:</strong> It is a client responsibility to recycle the
+ * received info by calling {@link AccessibilityNodeInfo#recycle()}
+ * to avoid creating of multiple instances.
+ * </p>
*
* @param text The searched text.
* @return A list of node info.
@@ -260,7 +282,7 @@
public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
enforceSealed();
if (!canPerformRequestOverConnection(mAccessibilityViewId)) {
- return null;
+ return Collections.emptyList();
}
try {
return mConnection.findAccessibilityNodeInfosByViewText(text, mAccessibilityWindowId,
@@ -274,12 +296,11 @@
/**
* Gets the unique id identifying this node's parent.
* <p>
- * <strong>
- * It is a client responsibility to recycle the received info by
- * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
- * of multiple instances.
- * </strong>
+ * <strong>Note:</strong> It is a client responsibility to recycle the
+ * received info by calling {@link AccessibilityNodeInfo#recycle()}
+ * to avoid creating of multiple instances.
* </p>
+ *
* @return The node's patent id.
*/
public AccessibilityNodeInfo getParent() {
@@ -299,9 +320,11 @@
/**
* Sets the parent.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param parent The parent.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -324,9 +347,11 @@
/**
* Sets the node bounds in parent coordinates.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param bounds The node bounds.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -349,9 +374,11 @@
/**
* Sets the node bounds in screen coordinates.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param bounds The node bounds.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -373,9 +400,11 @@
/**
* Sets whether this node is checkable.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param checkable True if the node is checkable.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -396,9 +425,11 @@
/**
* Sets whether this node is checked.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param checked True if the node is checked.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -419,9 +450,11 @@
/**
* Sets whether this node is focusable.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param focusable True if the node is focusable.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -442,9 +475,11 @@
/**
* Sets whether this node is focused.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param focused True if the node is focused.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -465,9 +500,11 @@
/**
* Sets whether this node is selected.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param selected True if the node is selected.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -488,9 +525,11 @@
/**
* Sets whether this node is clickable.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param clickable True if the node is clickable.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -511,9 +550,11 @@
/**
* Sets whether this node is long clickable.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param longClickable True if the node is long clickable.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -534,9 +575,11 @@
/**
* Sets whether this node is enabled.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param enabled True if the node is enabled.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -557,9 +600,11 @@
/**
* Sets whether this node is a password.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param password True if the node is a password.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -569,6 +614,32 @@
}
/**
+ * Gets if the node is scrollable.
+ *
+ * @return True if the node is scrollable, false otherwise.
+ */
+ public boolean isScrollable() {
+ return getBooleanProperty(PROPERTY_SCROLLABLE);
+ }
+
+ /**
+ * Sets if the node is scrollable.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param scrollable True if the node is scrollable, false otherwise.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setScrollable(boolean scrollable) {
+ enforceNotSealed();
+ setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+ }
+
+ /**
* Gets the package this node comes from.
*
* @return The package name.
@@ -580,9 +651,11 @@
/**
* Sets the package this node comes from.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param packageName The package name.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -604,9 +677,11 @@
/**
* Sets the class this node comes from.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param className The class name.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -628,9 +703,11 @@
/**
* Sets the text of this node.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param text The text.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -652,9 +729,11 @@
/**
* Sets the content description of this node.
* <p>
- * Note: Cannot be called from an {@link android.accessibilityservice.AccessibilityService}.
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
* This class is made immutable before being delivered to an AccessibilityService.
* </p>
+ *
* @param contentDescription The content description.
*
* @throws IllegalStateException If called from an AccessibilityService.
@@ -796,7 +875,7 @@
/**
* Return an instance back to be reused.
* <p>
- * <b>Note: You must not touch the object after calling this function.</b>
+ * <strong>Note:</strong> You must not touch the object after calling this function.
*
* @throws IllegalStateException If the info is already recycled.
*/
@@ -818,8 +897,8 @@
/**
* {@inheritDoc}
* <p>
- * <b>Note: After the instance is written to a parcel it is recycled.
- * You must not touch the object after calling this function.</b>
+ * <strong>Note:</strong> After the instance is written to a parcel it
+ * is recycled. You must not touch the object after calling this function.
* </p>
*/
public void writeToParcel(Parcel parcel, int flags) {
@@ -861,7 +940,7 @@
TextUtils.writeToParcel(mContentDescription, parcel, flags);
// Since instances of this class are fetched via synchronous i.e. blocking
- // calls in IPCs and we always recycle as soon as the instance is marshaled.
+ // calls in IPCs we always recycle as soon as the instance is marshaled.
recycle();
}
@@ -933,15 +1012,18 @@
* @return The symbolic name.
*/
private static String getActionSymbolicName(int action) {
- SparseArray<String> actionSymbolicNames = sActionSymbolicNames;
- if (actionSymbolicNames == null) {
- actionSymbolicNames = sActionSymbolicNames = new SparseArray<String>();
- actionSymbolicNames.put(ACTION_FOCUS, "ACTION_FOCUS");
- actionSymbolicNames.put(ACTION_CLEAR_FOCUS, "ACTION_UNFOCUS");
- actionSymbolicNames.put(ACTION_SELECT, "ACTION_SELECT");
- actionSymbolicNames.put(ACTION_CLEAR_SELECTION, "ACTION_UNSELECT");
+ switch (action) {
+ case ACTION_FOCUS:
+ return "ACTION_FOCUS";
+ case ACTION_CLEAR_FOCUS:
+ return "ACTION_CLEAR_FOCUS";
+ case ACTION_SELECT:
+ return "ACTION_SELECT";
+ case ACTION_CLEAR_SELECTION:
+ return "ACTION_CLEAR_SELECTION";
+ default:
+ throw new IllegalArgumentException("Unknown action: " + action);
}
- return actionSymbolicNames.get(action);
}
private boolean canPerformRequestOverConnection(int accessibilityViewId) {
@@ -1016,6 +1098,7 @@
builder.append("; longClickable: ").append(isLongClickable());
builder.append("; enabled: ").append(isEnabled());
builder.append("; password: ").append(isPassword());
+ builder.append("; scrollable: " + isScrollable());
builder.append("; [");
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 9c495e21..f4d5e89 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -25,12 +25,28 @@
import java.util.List;
/**
- * Represents a record in an accessibility event. This class encapsulates
- * the information for a {@link android.view.View}. Note that not all properties
- * are applicable to all view types. For detailed information please refer to
- * {@link AccessibilityEvent}.
+ * Represents a record in an {@link AccessibilityEvent} and contains information
+ * about state change of its source {@link android.view.View}. When a view fires
+ * an accessibility event it requests from its parent to dispatch the
+ * constructed event. The parent may optionally append a record for itself
+ * for providing more context to
+ * {@link android.accessibilityservice.AccessibilityService}s. Hence,
+ * accessibility services can facilitate additional accessibility records
+ * to enhance feedback.
+ * </p>
+ * <p>
+ * Once the accessibility event containing a record is dispatched the record is
+ * made immutable and calling a state mutation method generates an error.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Not all properties are applicable to all accessibility
+ * event types. For detailed information please refer to {@link AccessibilityEvent}.
+ * </p>
*
* @see AccessibilityEvent
+ * @see AccessibilityManager
+ * @see android.accessibilityservice.AccessibilityService
+ * @see AccessibilityNodeInfo
*/
public class AccessibilityRecord {
@@ -40,6 +56,7 @@
private static final int PROPERTY_ENABLED = 0x00000002;
private static final int PROPERTY_PASSWORD = 0x00000004;
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
+ private static final int PROPERTY_SCROLLABLE = 0x00000100;
// Housekeeping
private static final int MAX_POOL_SIZE = 10;
@@ -54,6 +71,10 @@
int mCurrentItemIndex;
int mItemCount;
int mFromIndex;
+ int mToIndex;
+ int mScrollX;
+ int mScrollY;
+
int mAddedCount;
int mRemovedCount;
int mSourceViewId = View.NO_ID;
@@ -71,30 +92,6 @@
* Hide constructor.
*/
AccessibilityRecord() {
-
- }
-
- /**
- * Initialize this record from another one.
- *
- * @param record The to initialize from.
- */
- void init(AccessibilityRecord record) {
- mSealed = record.mSealed;
- mBooleanProperties = record.mBooleanProperties;
- mCurrentItemIndex = record.mCurrentItemIndex;
- mItemCount = record.mItemCount;
- mFromIndex = record.mFromIndex;
- mAddedCount = record.mAddedCount;
- mRemovedCount = record.mRemovedCount;
- mClassName = record.mClassName;
- mContentDescription = record.mContentDescription;
- mBeforeText = record.mBeforeText;
- mParcelableData = record.mParcelableData;
- mText.addAll(record.mText);
- mSourceWindowId = record.mSourceWindowId;
- mSourceViewId = record.mSourceViewId;
- mConnection = record.mConnection;
}
/**
@@ -118,13 +115,12 @@
/**
* Gets the {@link AccessibilityNodeInfo} of the event source.
* <p>
- * <strong>
- * It is a client responsibility to recycle the received info by
- * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating
- * of multiple instances.
- * </strong>
+ * <strong>Note:</strong> It is a client responsibility to recycle the received info
+ * by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
+ * to avoid creating of multiple instances.
+ *
* </p>
- * @return The info.
+ * @return The info of the source.
*/
public AccessibilityNodeInfo getSource() {
enforceSealed();
@@ -246,6 +242,27 @@
}
/**
+ * Gets if the source is scrollable.
+ *
+ * @return True if the source is scrollable, false otherwise.
+ */
+ public boolean isScrollable() {
+ return getBooleanProperty(PROPERTY_SCROLLABLE);
+ }
+
+ /**
+ * Sets if the source is scrollable.
+ *
+ * @param scrollable True if the source is scrollable, false otherwise.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setScrollable(boolean scrollable) {
+ enforceNotSealed();
+ setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+ }
+
+ /**
* Gets the number of items that can be visited.
*
* @return The number of items.
@@ -288,18 +305,24 @@
}
/**
- * Gets the index of the first character of the changed sequence.
+ * Gets the index of the first character of the changed sequence,
+ * or the beginning of a text selection or the index of the first
+ * visible item when scrolling.
*
- * @return The index of the first character.
+ * @return The index of the first character or selection
+ * start or the first visible item.
*/
public int getFromIndex() {
return mFromIndex;
}
/**
- * Sets the index of the first character of the changed sequence.
+ * Sets the index of the first character of the changed sequence
+ * or the beginning of a text selection or the index of the first
+ * visible item when scrolling.
*
- * @param fromIndex The index of the first character.
+ * @param fromIndex The index of the first character or selection
+ * start or the first visible item.
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
@@ -309,6 +332,65 @@
}
/**
+ * Gets the index of text selection end or the index of the last
+ * visible item when scrolling.
+ *
+ * @return The index of selection end or last item index.
+ */
+ public int getToIndex() {
+ return mToIndex;
+ }
+
+ /**
+ * Sets the index of text selection end or the index of the last
+ * visible item when scrolling.
+ *
+ * @param toIndex The index of selection end or last item index.
+ */
+ public void setToIndex(int toIndex) {
+ enforceNotSealed();
+ mToIndex = toIndex;
+ }
+
+ /**
+ * Gets the scroll position of the source along the X axis.
+ *
+ * @return The scroll along the X axis.
+ */
+ public int getScrollX() {
+ return mScrollX;
+ }
+
+ /**
+ * Sets the scroll position of the source along the X axis.
+ *
+ * @param scrollX The scroll along the X axis.
+ */
+ public void setScrollX(int scrollX) {
+ enforceNotSealed();
+ mScrollX = scrollX;
+ }
+
+ /**
+ * Gets the scroll position of the source along the Y axis.
+ *
+ * @return The scroll along the Y axis.
+ */
+ public int getScrollY() {
+ return mScrollY;
+ }
+
+ /**
+ * Sets the scroll position of the source along the Y axis.
+ *
+ * @param scrollY The scroll along the Y axis.
+ */
+ public void setScrollY(int scrollY) {
+ enforceNotSealed();
+ mScrollY = scrollY;
+ }
+
+ /**
* Gets the number of added characters.
*
* @return The number of added characters.
@@ -548,7 +630,7 @@
/**
* Return an instance back to be reused.
* <p>
- * <b>Note: You must not touch the object after calling this function.</b>
+ * <strong>Note:</strong> You must not touch the object after calling this function.
*
* @throws IllegalStateException If the record is already recycled.
*/
@@ -568,6 +650,32 @@
}
/**
+ * Initialize this record from another one.
+ *
+ * @param record The to initialize from.
+ */
+ void init(AccessibilityRecord record) {
+ mSealed = record.mSealed;
+ mBooleanProperties = record.mBooleanProperties;
+ mCurrentItemIndex = record.mCurrentItemIndex;
+ mItemCount = record.mItemCount;
+ mFromIndex = record.mFromIndex;
+ mToIndex = record.mToIndex;
+ mScrollX = record.mScrollX;
+ mScrollY = record.mScrollY;
+ mAddedCount = record.mAddedCount;
+ mRemovedCount = record.mRemovedCount;
+ mClassName = record.mClassName;
+ mContentDescription = record.mContentDescription;
+ mBeforeText = record.mBeforeText;
+ mParcelableData = record.mParcelableData;
+ mText.addAll(record.mText);
+ mSourceWindowId = record.mSourceWindowId;
+ mSourceViewId = record.mSourceViewId;
+ mConnection = record.mConnection;
+ }
+
+ /**
* Clears the state of this instance.
*/
void clear() {
@@ -576,6 +684,9 @@
mCurrentItemIndex = INVALID_POSITION;
mItemCount = 0;
mFromIndex = 0;
+ mToIndex = 0;
+ mScrollX = 0;
+ mScrollY = 0;
mAddedCount = 0;
mRemovedCount = 0;
mClassName = null;
@@ -599,8 +710,12 @@
builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
+ builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
builder.append("; BeforeText: " + mBeforeText);
builder.append("; FromIndex: " + mFromIndex);
+ builder.append("; ToIndex: " + mToIndex);
+ builder.append("; ScrollX: " + mScrollX);
+ builder.append("; ScrollY: " + mScrollY);
builder.append("; AddedCount: " + mAddedCount);
builder.append("; RemovedCount: " + mRemovedCount);
builder.append("; ParcelableData: " + mParcelableData);
diff --git a/core/java/android/view/accessibility/package.html b/core/java/android/view/accessibility/package.html
new file mode 100644
index 0000000..4afafd3
--- /dev/null
+++ b/core/java/android/view/accessibility/package.html
@@ -0,0 +1,39 @@
+<html>
+<body>
+<p>
+ The classes in this package are used to represent screen content and changes to it
+ as well as APIs for querying the global accessibility state of the system.
+</p>
+<p>
+ {@link android.view.accessibility.AccessibilityEvent}s are sent by the system when
+ something notable happens in the user interface. For example, when a
+ {@link android.widget.Button} is clicked, a {@link android.view.View} is focused, etc.
+</p>
+<p>
+ {@link android.view.accessibility.AccessibilityRecord} contains information
+ about state change of its source {@link android.view.View}. When a view fires
+ an accessibility event it requests from its parent to dispatch the
+ constructed event. The parent may optionally append a record for itself for
+ providing more context to {@link android.accessibilityservice.AccessibilityService}s.
+ Hence, accessibility services can facilitate additional accessibility records
+ to enhance feedback.
+</p>
+<p>
+ {@link android.view.accessibility.AccessibilityNodeInfo} represents a node of the
+ window content as well as actions that can be requested from its source. From the point
+ of view of an {@link android.accessibilityservice.AccessibilityService} a window content is
+ presented as tree of accessibility node info which may or may not map one-to-one
+ to the view hierarchy. In other words, a custom view is free to report itself as
+ a tree of accessibility node info.
+</p>
+<p>
+ {@link android.view.accessibility.AccessibilityManager} is a system level service that
+ serves as an event dispatch for {@link android.view.accessibility.AccessibilityEvent}s,
+ and provides facilities for querying the accessibility state of the system. Accessibility
+ events are generated when something notable happens in the user interface, for example an
+ {@link android.app.Activity} starts, the focus or selection of a {@link android.view.View}
+ changes etc. Parties interested in handling accessibility events implement and register an
+ accessibility service which extends {@link android.accessibilityservice.AccessibilityService}.
+</p>
+</body>
+</html>
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 47f5e4c..a1a7281 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1126,7 +1126,7 @@
if (mServedView == mNextServedView && !mNextServedNeedsStart) {
return;
}
-
+
InputConnection ic = null;
synchronized (mH) {
if (mServedView == mNextServedView && !mNextServedNeedsStart) {
@@ -1242,6 +1242,27 @@
}
/**
+ * Notify the event when the user tapped or clicked the text view.
+ */
+ public void viewClicked(View view) {
+ final boolean focusChanged = mServedView != mNextServedView;
+ checkFocus();
+ synchronized (mH) {
+ if ((mServedView != view && (mServedView == null
+ || !mServedView.checkInputConnectionProxy(view)))
+ || mCurrentTextBoxAttribute == null || mCurMethod == null) {
+ return;
+ }
+ try {
+ if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
+ mCurMethod.viewClicked(focusChanged);
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
+ }
+ }
+ }
+
+ /**
* Returns true if the current input method wants to watch the location
* of the input editor's cursor in its window.
*/
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index bb03afa..ea6f5ee 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -63,6 +63,15 @@
int candidatesStart, int candidatesEnd);
/**
+ * This method is called when the user tapped a text view.
+ * IMEs can't rely on this method being called because this was not part of the original IME
+ * protocol, so applications with custom text editing written before this method appeared will
+ * not call to inform the IME of this interaction.
+ * @param focusChanged true if the user changed the focused view by this click.
+ */
+ public void viewClicked(boolean focusChanged);
+
+ /**
* This method is called when cursor location of the target input field
* has changed within its window. This is not normally called, but will
* only be reported if requested by the input method.
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 2f4774f..79a5aff 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1150,11 +1150,12 @@
* {@link #nativeSslCertErrorProceed(int)} or
* {@link #nativeSslCertErrorCancel(int, int)}.
*/
- private void reportSslCertError(final int handle, final int cert_error, byte cert_der[]) {
+ private void reportSslCertError(
+ final int handle, final int cert_error, byte cert_der[], String url) {
final SslError ssl_error;
try {
X509Certificate cert = new X509CertImpl(cert_der);
- ssl_error = new SslError(cert_error, cert);
+ ssl_error = new SslError(cert_error, cert, url);
} catch (IOException e) {
// Can't get the certificate, not much to do.
Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling");
diff --git a/core/java/android/webkit/CertTool.java b/core/java/android/webkit/CertTool.java
index 4c534f9..a2325c3 100644
--- a/core/java/android/webkit/CertTool.java
+++ b/core/java/android/webkit/CertTool.java
@@ -21,31 +21,27 @@
import com.android.org.bouncycastle.jce.netscape.NetscapeCertRequest;
import com.android.org.bouncycastle.util.encoders.Base64;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.Intent;
import android.security.Credentials;
+import android.security.KeyChain;
import android.util.Log;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.HashMap;
-class CertTool {
+final class CertTool {
private static final String LOGTAG = "CertTool";
private static final AlgorithmIdentifier MD5_WITH_RSA =
new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption);
- static final String CERT = Credentials.CERTIFICATE;
- static final String PKCS12 = Credentials.PKCS12;
-
private static HashMap<String, String> sCertificateTypeMap;
static {
sCertificateTypeMap = new HashMap<String, String>();
- sCertificateTypeMap.put("application/x-x509-ca-cert", CertTool.CERT);
- sCertificateTypeMap.put("application/x-x509-user-cert", CertTool.CERT);
- sCertificateTypeMap.put("application/x-pkcs12", CertTool.PKCS12);
+ sCertificateTypeMap.put("application/x-x509-ca-cert", KeyChain.EXTRA_CERTIFICATE);
+ sCertificateTypeMap.put("application/x-x509-user-cert", KeyChain.EXTRA_CERTIFICATE);
+ sCertificateTypeMap.put("application/x-pkcs12", KeyChain.EXTRA_PKCS12);
}
static String[] getKeyStrengthList() {
@@ -77,7 +73,7 @@
static String getCertType(String mimeType) {
return sCertificateTypeMap.get(mimeType);
- }
+ }
private CertTool() {}
}
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 4cae9d8..11ab0d7 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -104,9 +104,13 @@
public void surfaceDestroyed(SurfaceHolder holder)
{
- // after we return from this we can't use the surface any more
- mSurfaceHolder = null;
+ // After we return from this we can't use the surface any more.
// The current Video View will be destroy when we play a new video.
+ pauseAndDispatch(mProxy);
+ mSurfaceHolder = null;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
}
};
@@ -210,7 +214,6 @@
// which happens when the video view is detached from its parent
// view. This happens in the WebChromeClient before this method
// is invoked.
- pauseAndDispatch(mProxy);
mProxy.dispatchOnStopFullScreen();
mLayout.removeView(getSurfaceView());
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index b5d4933..bb4d192 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -23,6 +23,10 @@
import java.io.InputStream;
class JniUtil {
+
+ static {
+ System.loadLibrary("webcore");
+ }
private static final String LOGTAG = "webkit";
private JniUtil() {} // Utility class, do not instantiate.
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index c361a4a..761007f 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -59,6 +59,7 @@
* NORMAL is 100%
* LARGER is 150%
* LARGEST is 200%
+ * @deprecated Use {@link WebSettings#setTextZoom(int)} and {@link WebSettings#getTextZoom()} instead.
*/
public enum TextSize {
SMALLEST(50),
@@ -158,7 +159,7 @@
// know what they are.
private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
private Context mContext;
- private TextSize mTextSize = TextSize.NORMAL;
+ private int mTextSize = 100;
private String mStandardFontFamily = "sans-serif";
private String mFixedFontFamily = "monospace";
private String mSansSerifFontFamily = "sans-serif";
@@ -709,26 +710,61 @@
}
/**
- * Set the text size of the page.
- * @param t A TextSize value for increasing or decreasing the text.
- * @see WebSettings.TextSize
+ * Set the text zoom of the page in percent. Default is 100.
+ * @param textZoom A percent value for increasing or decreasing the text.
*/
- public synchronized void setTextSize(TextSize t) {
- if (WebView.mLogEvent && mTextSize != t ) {
- EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
- mTextSize.value, t.value);
+ public synchronized void setTextZoom(int textZoom) {
+ if (mTextSize != textZoom) {
+ if (WebView.mLogEvent) {
+ EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
+ mTextSize, textZoom);
+ }
+ mTextSize = textZoom;
+ postSync();
}
- mTextSize = t;
- postSync();
}
/**
- * Get the text size of the page.
+ * Get the text zoom of the page in percent.
+ * @return A percent value describing the text zoom.
+ * @see setTextSizeZoom
+ */
+ public synchronized int getTextZoom() {
+ return mTextSize;
+ }
+
+ /**
+ * Set the text size of the page.
+ * @param t A TextSize value for increasing or decreasing the text.
+ * @see WebSettings.TextSize
+ * @deprecated Use {@link #setTextZoom(int)} instead
+ */
+ public synchronized void setTextSize(TextSize t) {
+ setTextZoom(t.value);
+ }
+
+ /**
+ * Get the text size of the page. If the text size was previously specified
+ * in percent using {@link #setTextZoom(int)}, this will return
+ * the closest matching {@link TextSize}.
* @return A TextSize enum value describing the text size.
* @see WebSettings.TextSize
+ * @deprecated Use {@link #getTextZoom()} instead
*/
public synchronized TextSize getTextSize() {
- return mTextSize;
+ TextSize closestSize = null;
+ int smallestDelta = Integer.MAX_VALUE;
+ for (TextSize size : TextSize.values()) {
+ int delta = Math.abs(mTextSize - size.value);
+ if (delta == 0) {
+ return size;
+ }
+ if (delta < smallestDelta) {
+ smallestDelta = delta;
+ closestSize = size;
+ }
+ }
+ return closestSize != null ? closestSize : TextSize.NORMAL;
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c56e6db..9f632d1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5707,8 +5707,8 @@
return false;
}
WebViewCore.CursorData data = cursorDataNoPosition();
- data.mX = viewToContentX((int) event.getX());
- data.mY = viewToContentY((int) event.getY());
+ data.mX = viewToContentX((int) event.getX() + mScrollX);
+ data.mY = viewToContentY((int) event.getY() + mScrollY);
mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
return true;
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 06a61bd..4f97066 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1950,6 +1950,7 @@
// mInitialViewState is set by didFirstLayout() and then reset in the
// next webkitDraw after passing the state to the UI thread.
private ViewState mInitialViewState = null;
+ private boolean mFirstLayoutForNonStandardLoad;
static class ViewState {
float mMinScale;
@@ -1977,6 +1978,7 @@
int mMinPrefWidth;
// only non-null if it is for the first picture set after the first layout
ViewState mViewState;
+ boolean mFirstLayoutForNonStandardLoad;
boolean mFocusSizeChanged;
}
@@ -2000,8 +2002,12 @@
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
draw.mBaseLayer = nativeRecordContent(draw.mInvalRegion, draw.mContentSize);
if (draw.mBaseLayer == 0) {
- if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
- mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+ if (mWebView != null && !mWebView.isPaused()) {
+ if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
+ mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+ } else {
+ if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, webview paused");
+ }
return;
}
webkitDraw(draw);
@@ -2022,6 +2028,10 @@
draw.mViewState = mInitialViewState;
mInitialViewState = null;
}
+ if (mFirstLayoutForNonStandardLoad) {
+ draw.mFirstLayoutForNonStandardLoad = true;
+ mFirstLayoutForNonStandardLoad = false;
+ }
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
Message.obtain(mWebView.mPrivateHandler,
WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -2308,6 +2318,8 @@
// if mViewportWidth is 0, it means device-width, always update.
if (mViewportWidth != 0 && !updateViewState) {
+ // For non standard load, since updateViewState will be false.
+ mFirstLayoutForNonStandardLoad = true;
ViewState viewState = new ViewState();
viewState.mMinScale = mViewportMinimumScale / 100.0f;
viewState.mMaxScale = mViewportMaximumScale / 100.0f;
@@ -2358,7 +2370,7 @@
mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
mViewportInitialScale / 100.0f;
} else if (mViewportWidth > 0 && mViewportWidth < webViewWidth &&
- !mWebView.getSettings().getUseFixedViewport()) {
+ !getSettings().getUseFixedViewport()) {
mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
(float) webViewWidth / mViewportWidth;
} else {
@@ -2467,9 +2479,10 @@
// called by JNI
private void restoreScale(float scale, float textWrapScale) {
if (mBrowserFrame.firstLayoutDone() == false) {
- mRestoredScale = scale;
+ final float defaultScale = mWebView.getDefaultZoomScale();
+ mRestoredScale = (scale <= 0.0) ? defaultScale : scale;
if (mSettings.getUseWideViewPort()) {
- mRestoredTextWrapScale = textWrapScale;
+ mRestoredTextWrapScale = (textWrapScale <= 0.0) ? defaultScale : textWrapScale;
}
}
}
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 883656b..7d43e94 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -1024,6 +1024,11 @@
} else {
mInZoomOverview = !scaleHasDiff;
}
+ if (drawData.mFirstLayoutForNonStandardLoad && settings.getLoadWithOverviewMode()) {
+ // Set mInitialZoomOverview in case this is the first picture for non standard load,
+ // so next new picture could be forced into overview mode if it's true.
+ mInitialZoomOverview = mInZoomOverview;
+ }
}
/**
@@ -1107,7 +1112,8 @@
}
reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
}
- mInitialZoomOverview = !exceedsMinScaleIncrement(scale, overviewScale);
+ mInitialZoomOverview = settings.getLoadWithOverviewMode() &&
+ !exceedsMinScaleIncrement(scale, overviewScale);
setZoomScale(scale, reflowText);
// update the zoom buttons as the scale can be changed
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3fe8149..1449b18 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,6 +55,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -1257,6 +1259,33 @@
onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ event.setFromIndex(mFirstPosition);
+ event.setToIndex(mFirstPosition + getChildCount());
+ event.setItemCount(mItemCount);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
/**
* Indicates whether the children's drawing cache is used during a scroll.
* By default, the drawing cache is enabled but this will consume more memory.
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index ce76bee..0ffd087 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -34,6 +34,8 @@
import android.view.ViewGroup;
import android.view.SoundEffectConstants;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Transformation;
/**
@@ -344,7 +346,34 @@
int getChildHeight(View child) {
return child.getMeasuredHeight();
}
-
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ event.setFromIndex(mFirstPosition);
+ event.setToIndex(mFirstPosition + getChildCount());
+ event.setItemCount(mItemCount);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
/**
* Tracks a motion scroll. In reality, this is used to do just about any
* movement to items (touch scroll, arrow-key scroll, set an item as selected).
@@ -382,7 +411,9 @@
mRecycler.clear();
setSelectionToCenterChild();
-
+
+ onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+
invalidate();
}
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index e54c511..1570224 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -38,8 +38,6 @@
import java.util.List;
import java.util.Map;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.UNSPECIFIED;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -135,11 +133,43 @@
*/
public static final int UNDEFINED = Integer.MIN_VALUE;
+ /**
+ * This constant is an {@link #setAlignmentMode(int) alignmentMode}.
+ * When the {@code alignmentMode} is set to {@link #ALIGN_BOUNDS}, alignment
+ * is made between the edges of each component's raw
+ * view boundary: i.e. the area delimited by the component's:
+ * {@link android.view.View#getTop() top},
+ * {@link android.view.View#getLeft() left},
+ * {@link android.view.View#getBottom() bottom} and
+ * {@link android.view.View#getRight() right} properties.
+ * <p>
+ * For example, when {@code GridLayout} is in {@link #ALIGN_BOUNDS} mode,
+ * children that belong to a row group that uses {@link #TOP} alignment will
+ * all return the same value when their {@link android.view.View#getTop()}
+ * method is called.
+ *
+ * @see #setAlignmentMode(int)
+ */
+ public static final int ALIGN_BOUNDS = 0;
+
+ /**
+ * This constant is an {@link #setAlignmentMode(int) alignmentMode}.
+ * When the {@code alignmentMode} is set to {@link #ALIGN_MARGINS},
+ * the bounds of each view are extended outwards, according
+ * to their margins, before the edges of the resulting rectangle are aligned.
+ * <p>
+ * For example, when {@code GridLayout} is in {@link #ALIGN_MARGINS} mode,
+ * the quantity {@code top - layoutParams.topMargin} is the same for all children that
+ * belong to a row group that uses {@link #TOP} alignment.
+ *
+ * @see #setAlignmentMode(int)
+ */
+ public static final int ALIGN_MARGINS = 1;
+
// Misc constants
private static final String TAG = GridLayout.class.getName();
private static final boolean DEBUG = false;
- private static final Paint GRID_PAINT = new Paint();
private static final double GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;
private static final int MIN = 0;
private static final int PRF = 1;
@@ -151,7 +181,7 @@
private static final int DEFAULT_COUNT = UNDEFINED;
private static final boolean DEFAULT_USE_DEFAULT_MARGINS = false;
private static final boolean DEFAULT_ORDER_PRESERVED = false;
- private static final boolean DEFAULT_MARGINS_INCLUDED = true;
+ private static final int DEFAULT_ALIGNMENT_MODE = ALIGN_MARGINS;
// todo remove this
private static final int DEFAULT_CONTAINER_MARGIN = 20;
@@ -161,16 +191,10 @@
private static final int ROW_COUNT = styleable.GridLayout_rowCount;
private static final int COLUMN_COUNT = styleable.GridLayout_columnCount;
private static final int USE_DEFAULT_MARGINS = styleable.GridLayout_useDefaultMargins;
- private static final int MARGINS_INCLUDED = styleable.GridLayout_marginsIncludedInAlignment;
+ private static final int ALIGNMENT_MODE = styleable.GridLayout_alignmentMode;
private static final int ROW_ORDER_PRESERVED = styleable.GridLayout_rowOrderPreserved;
private static final int COLUMN_ORDER_PRESERVED = styleable.GridLayout_columnOrderPreserved;
- // Static initialization
-
- static {
- GRID_PAINT.setColor(Color.argb(50, 255, 255, 255));
- }
-
// Instance variables
private final Axis mHorizontalAxis = new Axis(true);
@@ -178,7 +202,7 @@
private boolean mLayoutParamsValid = false;
private int mOrientation = DEFAULT_ORIENTATION;
private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
- private boolean mMarginsIncludedInAlignment = DEFAULT_MARGINS_INCLUDED;
+ private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
private int mDefaultGravity = Gravity.NO_GRAVITY;
/* package */ boolean accommodateBothMinAndMax = false;
@@ -213,11 +237,11 @@
private void processAttributes(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout);
try {
- setRowCount(a.getInteger(ROW_COUNT, DEFAULT_COUNT));
- setColumnCount(a.getInteger(COLUMN_COUNT, DEFAULT_COUNT));
- mOrientation = a.getInteger(ORIENTATION, DEFAULT_ORIENTATION);
+ setRowCount(a.getInt(ROW_COUNT, DEFAULT_COUNT));
+ setColumnCount(a.getInt(COLUMN_COUNT, DEFAULT_COUNT));
+ mOrientation = a.getInt(ORIENTATION, DEFAULT_ORIENTATION);
mUseDefaultMargins = a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS);
- mMarginsIncludedInAlignment = a.getBoolean(MARGINS_INCLUDED, DEFAULT_MARGINS_INCLUDED);
+ mAlignmentMode = a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE);
setRowOrderPreserved(a.getBoolean(ROW_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED));
setColumnOrderPreserved(a.getBoolean(COLUMN_ORDER_PRESERVED, DEFAULT_ORDER_PRESERVED));
} finally {
@@ -347,15 +371,15 @@
* When {@code false}, the default value of all margins is zero.
* <p>
* When setting to {@code true}, consider setting the value of the
- * {@link #setMarginsIncludedInAlignment(boolean) marginsIncludedInAlignment}
- * property to {@code false}.
+ * {@link #setAlignmentMode(int) alignmentMode}
+ * property to {@link #ALIGN_BOUNDS}.
* <p>
* The default value of this property is {@code false}.
*
* @param useDefaultMargins use {@code true} to make GridLayout allocate default margins
*
* @see #getUseDefaultMargins()
- * @see #setMarginsIncludedInAlignment(boolean)
+ * @see #setAlignmentMode(int)
*
* @see MarginLayoutParams#leftMargin
* @see MarginLayoutParams#topMargin
@@ -370,36 +394,38 @@
}
/**
- * Returns whether GridLayout aligns the edges of the view or the edges
- * of the larger rectangle created by extending the view by its associated
- * margins.
+ * Returns the alignment mode.
*
- * @see #setMarginsIncludedInAlignment(boolean)
+ * @return the alignment mode; either {@link #ALIGN_BOUNDS} or {@link #ALIGN_MARGINS}
*
- * @return {@code true} if alignment is between edges including margins
+ * @see #ALIGN_BOUNDS
+ * @see #ALIGN_MARGINS
*
- * @attr ref android.R.styleable#GridLayout_marginsIncludedInAlignment
+ * @see #setAlignmentMode(int)
+ *
+ * @attr ref android.R.styleable#GridLayout_alignmentMode
*/
- public boolean getMarginsIncludedInAlignment() {
- return mMarginsIncludedInAlignment;
+ public int getAlignmentMode() {
+ return mAlignmentMode;
}
/**
- * When {@code true}, the bounds of a view are extended outwards according to its
- * margins before the edges of the resulting rectangle are aligned.
- * When {@code false}, alignment occurs between the bounds of the view - i.e.
- * {@link #LEFT} alignment means align the left edges of the view.
+ * Sets the alignment mode to be used for all of the alignments between the
+ * children of this container.
* <p>
- * The default value of this property is {@code true}.
+ * The default value of this property is {@link #ALIGN_MARGINS}.
*
- * @param marginsIncludedInAlignment {@code true} if alignment between edges includes margins
+ * @param alignmentMode either {@link #ALIGN_BOUNDS} or {@link #ALIGN_MARGINS}
*
- * @see #getMarginsIncludedInAlignment()
+ * @see #ALIGN_BOUNDS
+ * @see #ALIGN_MARGINS
*
- * @attr ref android.R.styleable#GridLayout_marginsIncludedInAlignment
+ * @see #getAlignmentMode()
+ *
+ * @attr ref android.R.styleable#GridLayout_alignmentMode
*/
- public void setMarginsIncludedInAlignment(boolean marginsIncludedInAlignment) {
- mMarginsIncludedInAlignment = marginsIncludedInAlignment;
+ public void setAlignmentMode(int alignmentMode) {
+ mAlignmentMode = alignmentMode;
requestLayout();
}
@@ -509,7 +535,7 @@
return result;
}
- private int getDefaultMargin(View c, boolean leading, boolean horizontal) {
+ private int getDefaultMargin(View c, boolean horizontal, boolean leading) {
// In the absence of any other information, calculate a default gap such
// that, in a grid of identical components, the heights and the vertical
// gaps are in the proportion of the golden ratio.
@@ -518,12 +544,12 @@
return (int) (c.getMeasuredHeight() / GOLDEN_RATIO / 2);
}
- private int getDefaultMargin(View c, boolean isAtEdge, boolean leading, boolean horizontal) {
+ private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
// todo remove DEFAULT_CONTAINER_MARGIN. Use padding? Seek advice on Themes/Styles, etc.
- return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, leading, horizontal);
+ return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
}
- private int getDefaultMarginValue(View c, LayoutParams p, boolean leading, boolean horizontal) {
+ private int getDefaultMarginValue(View c, LayoutParams p, boolean horizontal, boolean leading) {
if (!mUseDefaultMargins) {
return 0;
}
@@ -532,15 +558,19 @@
Interval span = group.span;
boolean isAtEdge = leading ? (span.min == 0) : (span.max == axis.getCount());
- return getDefaultMargin(c, isAtEdge, leading, horizontal);
+ return getDefaultMargin(c, isAtEdge, horizontal, leading);
}
- private int getMargin(View view, boolean leading, boolean horizontal) {
+ private int getMargin(View view, boolean horizontal, boolean leading) {
LayoutParams lp = getLayoutParams(view);
int margin = horizontal ?
(leading ? lp.leftMargin : lp.rightMargin) :
(leading ? lp.topMargin : lp.bottomMargin);
- return margin == UNDEFINED ? getDefaultMarginValue(view, lp, leading, horizontal) : margin;
+ return margin == UNDEFINED ? getDefaultMarginValue(view, lp, horizontal, leading) : margin;
+ }
+
+ private int getTotalMargin(View child, boolean horizontal) {
+ return getMargin(child, horizontal, true) + getMargin(child, horizontal, false);
}
private static int valueIfDefined(int value, int defaultValue) {
@@ -569,7 +599,9 @@
int row = 0;
int col = 0;
for (int i = 0, N = getChildCount(); i < N; i++) {
- LayoutParams lp = getLayoutParams1(getChildAt(i));
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams lp = getLayoutParams1(c);
Group colGroup = lp.columnGroup;
Interval cols = colGroup.span;
@@ -667,6 +699,15 @@
graphics.drawLine(dx + x1, dy + y1, dx + x2, dy + y2, paint);
}
+ private void drawRectangle(Canvas graphics, int x1, int y1, int x2, int y2, Paint paint) {
+ // x2 = x2 - 1;
+ // y2 = y2 - 1;
+ graphics.drawLine(x1, y1, x1, y2, paint);
+ graphics.drawLine(x1, y1, x2, y1, paint);
+ graphics.drawLine(x1, y2, x2, y2, paint);
+ graphics.drawLine(x2, y1, x2, y2, paint);
+ }
+
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -675,15 +716,46 @@
int height = getHeight() - getPaddingTop() - getPaddingBottom();
int width = getWidth() - getPaddingLeft() - getPaddingRight();
+ Paint paint = new Paint();
+ paint.setColor(Color.argb(50, 255, 255, 255));
+
int[] xs = mHorizontalAxis.locations;
- for (int i = 0, length = xs.length; i < length; i++) {
- int x = xs[i];
- drawLine(canvas, x, 0, x, height - 1, GRID_PAINT);
+ if (xs != null) {
+ for (int i = 0, length = xs.length; i < length; i++) {
+ int x = xs[i];
+ drawLine(canvas, x, 0, x, height - 1, paint);
+ }
}
+
int[] ys = mVerticalAxis.locations;
- for (int i = 0, length = ys.length; i < length; i++) {
- int y = ys[i];
- drawLine(canvas, 0, y, width - 1, y, GRID_PAINT);
+ if (ys != null) {
+ for (int i = 0, length = ys.length; i < length; i++) {
+ int y = ys[i];
+ drawLine(canvas, 0, y, width - 1, y, paint);
+ }
+ }
+ // Draw bounds
+ paint.setColor(Color.BLUE);
+
+ for (int i = 0; i < getChildCount(); i++) {
+ View c = getChildAt(i);
+ drawRectangle(canvas,
+ c.getLeft(),
+ c.getTop(),
+ c.getRight(),
+ c.getBottom(), paint);
+ }
+
+ // Draw margins
+ paint.setColor(Color.YELLOW);
+
+ for (int i = 0; i < getChildCount(); i++) {
+ View c = getChildAt(i);
+ drawRectangle(canvas,
+ c.getLeft() - getMargin(c, true, true),
+ c.getTop() - getMargin(c, false, true),
+ c.getRight() + getMargin(c, true, false),
+ c.getBottom() + getMargin(c, false, false), paint);
}
}
}
@@ -722,53 +794,40 @@
// Measurement
- private static int getChildMeasureSpec2(int spec, int padding, int childDimension) {
- int resultSize;
- int resultMode;
-
- if (childDimension >= 0) {
- resultSize = childDimension;
- resultMode = EXACTLY;
- } else {
- /*
- using the following lines would replicate the logic of ViewGroup.getChildMeasureSpec()
-
- int specMode = MeasureSpec.getMode(spec);
- int specSize = MeasureSpec.getSize(spec);
- int size = Math.max(0, specSize - padding);
-
- resultSize = size;
- resultMode = (specMode == EXACTLY && childDimension == LayoutParams.WRAP_CONTENT) ?
- AT_MOST : specMode;
- */
- resultSize = 0;
- resultMode = UNSPECIFIED;
- }
- return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
+ private boolean isGone(View c) {
+ return c.getVisibility() == View.GONE;
}
- @Override
- protected void measureChild(View child, int parentWidthSpec, int parentHeightSpec) {
- ViewGroup.LayoutParams lp = child.getLayoutParams();
-
- int childWidthMeasureSpec = getChildMeasureSpec2(parentWidthSpec,
- mPaddingLeft + mPaddingRight, lp.width);
- int childHeightMeasureSpec = getChildMeasureSpec2(parentHeightSpec,
- mPaddingTop + mPaddingBottom, lp.height);
-
+ private void measureChildWithMargins(View child, int widthMeasureSpec, int heightMeasureSpec) {
+ LayoutParams lp = getLayoutParams(child);
+ int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ mPaddingLeft + mPaddingRight + getTotalMargin(child, true), lp.width);
+ int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ mPaddingTop + mPaddingBottom + getTotalMargin(child, false), lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
+ private void measureChildrenWithMargins(int widthMeasureSpec, int heightMeasureSpec) {
+ for (int i = 0, N = getChildCount(); i < N; i++) {
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ measureChildWithMargins(c, widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
- measureChildren(widthSpec, heightSpec);
+ measureChildrenWithMargins(widthSpec, heightSpec);
int computedWidth = getPaddingLeft() + mHorizontalAxis.getMin() + getPaddingRight();
int computedHeight = getPaddingTop() + mVerticalAxis.getMin() + getPaddingBottom();
+ int measuredWidth = Math.max(computedWidth, getSuggestedMinimumWidth());
+ int measuredHeight = Math.max(computedHeight, getSuggestedMinimumHeight());
+
setMeasuredDimension(
- resolveSizeAndState(computedWidth, widthSpec, 0),
- resolveSizeAndState(computedHeight, heightSpec, 0));
+ resolveSizeAndState(measuredWidth, widthSpec, 0),
+ resolveSizeAndState(measuredHeight, heightSpec, 0));
}
private int protect(int alignment) {
@@ -781,10 +840,8 @@
private int getMeasurementIncludingMargin(View c, boolean horizontal, int measurementType) {
int result = getMeasurement(c, horizontal, measurementType);
- if (mMarginsIncludedInAlignment) {
- int leadingMargin = getMargin(c, true, horizontal);
- int trailingMargin = getMargin(c, false, horizontal);
- return result + leadingMargin + trailingMargin;
+ if (mAlignmentMode == ALIGN_MARGINS) {
+ return result + getTotalMargin(c, horizontal);
}
return result;
}
@@ -810,9 +867,9 @@
and sizing to each child view and then placing it in its cell.
*/
@Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int targetWidth = r - l;
- int targetHeight = b - t;
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int targetWidth = right - left;
+ int targetHeight = bottom - top;
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
@@ -822,26 +879,27 @@
mHorizontalAxis.layout(targetWidth - paddingLeft - paddingRight);
mVerticalAxis.layout(targetHeight - paddingTop - paddingBottom);
- for (int i = 0, size = getChildCount(); i < size; i++) {
- View view = getChildAt(i);
- LayoutParams lp = getLayoutParams(view);
+ for (int i = 0, N = getChildCount(); i < N; i++) {
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams lp = getLayoutParams(c);
Group columnGroup = lp.columnGroup;
Group rowGroup = lp.rowGroup;
Interval colSpan = columnGroup.span;
Interval rowSpan = rowGroup.span;
- int x1 = mHorizontalAxis.getLocationIncludingMargin(view, true, colSpan.min);
- int y1 = mVerticalAxis.getLocationIncludingMargin(view, true, rowSpan.min);
+ int x1 = mHorizontalAxis.getLocationIncludingMargin(c, true, colSpan.min);
+ int y1 = mVerticalAxis.getLocationIncludingMargin(c, true, rowSpan.min);
- int x2 = mHorizontalAxis.getLocationIncludingMargin(view, false, colSpan.max);
- int y2 = mVerticalAxis.getLocationIncludingMargin(view, false, rowSpan.max);
+ int x2 = mHorizontalAxis.getLocationIncludingMargin(c, false, colSpan.max);
+ int y2 = mVerticalAxis.getLocationIncludingMargin(c, false, rowSpan.max);
int cellWidth = x2 - x1;
int cellHeight = y2 - y1;
- int pWidth = getMeasurement(view, true, PRF);
- int pHeight = getMeasurement(view, false, PRF);
+ int pWidth = getMeasurement(c, true, PRF);
+ int pHeight = getMeasurement(c, false, PRF);
Alignment hAlign = columnGroup.alignment;
Alignment vAlign = rowGroup.alignment;
@@ -856,19 +914,19 @@
int c2ax = protect(hAlign.getAlignmentValue(null, cellWidth - colBounds.size(), type));
int c2ay = protect(vAlign.getAlignmentValue(null, cellHeight - rowBounds.size(), type));
- if (mMarginsIncludedInAlignment) {
- int leftMargin = getMargin(view, true, true);
- int topMargin = getMargin(view, true, false);
- int rightMargin = getMargin(view, false, true);
- int bottomMargin = getMargin(view, false, false);
+ if (mAlignmentMode == ALIGN_MARGINS) {
+ int leftMargin = getMargin(c, true, true);
+ int topMargin = getMargin(c, false, true);
+ int rightMargin = getMargin(c, true, false);
+ int bottomMargin = getMargin(c, false, false);
// Same calculation as getMeasurementIncludingMargin()
int mWidth = leftMargin + pWidth + rightMargin;
int mHeight = topMargin + pHeight + bottomMargin;
// Alignment offsets: the location of the view relative to its alignment group.
- int a2vx = colBounds.before - hAlign.getAlignmentValue(view, mWidth, type);
- int a2vy = rowBounds.before - vAlign.getAlignmentValue(view, mHeight, type);
+ int a2vx = colBounds.getOffset(c, hAlign, type, mWidth);
+ int a2vy = rowBounds.getOffset(c, vAlign, type, mHeight);
dx = c2ax + a2vx + leftMargin;
dy = c2ay + a2vy + topMargin;
@@ -877,19 +935,19 @@
cellHeight -= topMargin + bottomMargin;
} else {
// Alignment offsets: the location of the view relative to its alignment group.
- int a2vx = colBounds.before - hAlign.getAlignmentValue(view, pWidth, type);
- int a2vy = rowBounds.before - vAlign.getAlignmentValue(view, pHeight, type);
+ int a2vx = colBounds.getOffset(c, hAlign, type, pWidth);
+ int a2vy = rowBounds.getOffset(c, vAlign, type, pHeight);
dx = c2ax + a2vx;
dy = c2ay + a2vy;
}
- int width = hAlign.getSizeInCell(view, pWidth, cellWidth, type);
- int height = vAlign.getSizeInCell(view, pHeight, cellHeight, type);
+ int width = hAlign.getSizeInCell(c, pWidth, cellWidth, type);
+ int height = vAlign.getSizeInCell(c, pHeight, cellHeight, type);
int cx = paddingLeft + x1 + dx;
int cy = paddingTop + y1 + dy;
- view.layout(cx, cy, cx + width, cy + height);
+ c.layout(cx, cy, cx + width, cy + height);
}
}
@@ -944,8 +1002,10 @@
private int maxIndex() {
// note the number Integer.MIN_VALUE + 1 comes up in undefined cells
int count = -1;
- for (int i = 0, size = getChildCount(); i < size; i++) {
- LayoutParams params = getLayoutParams(getChildAt(i));
+ for (int i = 0, N = getChildCount(); i < N; i++) {
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams params = getLayoutParams(c);
Group g = horizontal ? params.columnGroup : params.rowGroup;
count = max(count, g.span.min);
count = max(count, g.span.max);
@@ -978,24 +1038,30 @@
private PackedMap<Group, Bounds> createGroupBounds() {
int N = getChildCount();
Group[] groups = new Group[N];
+ Arrays.fill(groups, Group.GONE);
Bounds[] bounds = new Bounds[N];
+ Arrays.fill(bounds, Bounds.GONE);
for (int i = 0; i < N; i++) {
- LayoutParams lp = getLayoutParams(getChildAt(i));
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams lp = getLayoutParams(c);
Group group = horizontal ? lp.columnGroup : lp.rowGroup;
groups[i] = group;
- bounds[i] = new Bounds();
+ bounds[i] = group.alignment.getBounds();
}
return new PackedMap<Group, Bounds>(groups, bounds);
}
private void computeGroupBounds() {
- for (int i = 0; i < groupBounds.values.length; i++) {
- groupBounds.values[i].reset();
+ Bounds[] values = groupBounds.values;
+ for (int i = 0; i < values.length; i++) {
+ values[i].reset();
}
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
+ if (isGone(c)) continue;
LayoutParams lp = getLayoutParams(c);
Group g = horizontal ? lp.columnGroup : lp.rowGroup;
@@ -1107,11 +1173,8 @@
return result;
}
- /*
- Topological sort.
- */
private Arc[] topologicalSort(final Arc[] arcs, int start) {
- // todo ensure the <start> vertex is added in edge cases
+ // todo ensure the <start> vertex is added in edge cases
final List<Arc> result = new ArrayList<Arc>();
new Object() {
Arc[][] arcsByFirstVertex = groupArcsByFirstVertex(arcs);
@@ -1160,11 +1223,13 @@
// todo unify with findUsed above. Both routines analyze which rows/columns are empty.
private Collection<Interval> getSpacers() {
List<Interval> result = new ArrayList<Interval>();
- int N = getCount() + 1;
- int[] leadingEdgeCount = new int[N];
- int[] trailingEdgeCount = new int[N];
- for (int i = 0, size = getChildCount(); i < size; i++) {
- LayoutParams lp = getLayoutParams(getChildAt(i));
+ int V = getCount() + 1;
+ int[] leadingEdgeCount = new int[V];
+ int[] trailingEdgeCount = new int[V];
+ for (int i = 0, N = getChildCount(); i < N; i++) {
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams lp = getLayoutParams(c);
Group g = horizontal ? lp.columnGroup : lp.rowGroup;
Interval span = g.span;
leadingEdgeCount[span.min]++;
@@ -1175,9 +1240,9 @@
// treat the parent's edges like peer edges of the opposite type
trailingEdgeCount[0] = 1;
- leadingEdgeCount[N - 1] = 1;
+ leadingEdgeCount[V - 1] = 1;
- for (int i = 0; i < N; i++) {
+ for (int i = 0; i < V; i++) {
if (trailingEdgeCount[i] > 0) {
lastTrailingEdge = i;
continue; // if this is also a leading edge, don't add a space of length zero
@@ -1190,24 +1255,25 @@
}
private Arc[] createArcs() {
- List<Arc> spanToSize = new ArrayList<Arc>();
+ List<Arc> result = new ArrayList<Arc>();
// Add all the preferred elements that were not defined by the user.
PackedMap<Interval, MutableInt> spanSizes = getSpanSizes();
for (int i = 0; i < spanSizes.keys.length; i++) {
Interval key = spanSizes.keys[i];
+ if (key == Interval.GONE) continue;
MutableInt value = spanSizes.values[i];
// todo remove value duplicate
- include2(spanToSize, key, value, value, accommodateBothMinAndMax);
+ include2(result, key, value, value, accommodateBothMinAndMax);
}
// Find redundant rows/cols and glue them together with 0-length arcs to link the tree
- boolean[] used = findUsed(spanToSize);
+ boolean[] used = findUsed(result);
for (int i = 0; i < getCount(); i++) {
if (!used[i]) {
Interval span = new Interval(i, i + 1);
- include(spanToSize, span, new MutableInt(0));
- include(spanToSize, span.inverse(), new MutableInt(0));
+ include(result, span, new MutableInt(0));
+ include(result, span.inverse(), new MutableInt(0));
}
}
@@ -1215,15 +1281,15 @@
// Add preferred gaps
for (int i = 0; i < getCount(); i++) {
if (used[i]) {
- include2(spanToSize, new Interval(i, i + 1), 0, 0, false);
+ include2(result, new Interval(i, i + 1), 0, 0, false);
}
}
} else {
for (Interval gap : getSpacers()) {
- include2(spanToSize, gap, 0, 0, false);
+ include2(result, gap, 0, 0, false);
}
}
- Arc[] arcs = spanToSize.toArray(new Arc[spanToSize.size()]);
+ Arc[] arcs = result.toArray(new Arc[result.size()]);
return topologicalSort(arcs, 0);
}
@@ -1311,13 +1377,14 @@
private void computeMargins(boolean leading) {
int[] margins = leading ? leadingMargins : trailingMargins;
- for (int i = 0, size = getChildCount(); i < size; i++) {
+ for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
+ if (isGone(c)) continue;
LayoutParams lp = getLayoutParams(c);
Group g = horizontal ? lp.columnGroup : lp.rowGroup;
Interval span = g.span;
int index = leading ? span.min : span.max;
- margins[index] = max(margins[index], getMargin(c, leading, horizontal));
+ margins[index] = max(margins[index], getMargin(c, horizontal, leading));
}
}
@@ -1358,7 +1425,7 @@
private int getLocationIncludingMargin(View view, boolean leading, int index) {
int location = locations[index];
int margin;
- if (!mMarginsIncludedInAlignment) {
+ if (mAlignmentMode != ALIGN_MARGINS) {
margin = (leading ? leadingMargins : trailingMargins)[index];
} else {
margin = 0;
@@ -1370,7 +1437,7 @@
Arrays.fill(a, MIN_VALUE);
a[0] = 0;
solve(getArcs(), a);
- if (!mMarginsIncludedInAlignment) {
+ if (mAlignmentMode != ALIGN_MARGINS) {
addMargins();
}
}
@@ -1389,7 +1456,9 @@
private void computeWeights() {
for (int i = 0, N = getChildCount(); i < N; i++) {
- LayoutParams lp = getLayoutParams(getChildAt(i));
+ View c = getChildAt(i);
+ if (isGone(c)) continue;
+ LayoutParams lp = getLayoutParams(c);
Group g = horizontal ? lp.columnGroup : lp.rowGroup;
Interval span = g.span;
int penultimateIndex = span.max - 1;
@@ -1745,22 +1814,23 @@
}
private int getDefaultWeight(int size) {
- return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+ //return (size == MATCH_PARENT) ? DEFAULT_WEIGHT_1 : DEFAULT_WEIGHT_0;
+ return DEFAULT_WEIGHT_0;
}
private void init(Context context, AttributeSet attrs, int defaultGravity) {
TypedArray a = context.obtainStyledAttributes(attrs, styleable.GridLayout_Layout);
try {
- int gravity = a.getInteger(GRAVITY, defaultGravity);
+ int gravity = a.getInt(GRAVITY, defaultGravity);
- int column = a.getInteger(COLUMN, DEFAULT_COLUMN);
- int columnSpan = a.getInteger(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
+ int column = a.getInt(COLUMN, DEFAULT_COLUMN);
+ int columnSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
Interval hSpan = new Interval(column, column + columnSpan);
this.columnGroup = new Group(hSpan, getColumnAlignment(gravity, width));
this.columnWeight = a.getFloat(COLUMN_WEIGHT, getDefaultWeight(width));
- int row = a.getInteger(ROW, DEFAULT_ROW);
- int rowSpan = a.getInteger(ROW_SPAN, DEFAULT_SPAN_SIZE);
+ int row = a.getInt(ROW, DEFAULT_ROW);
+ int rowSpan = a.getInt(ROW_SPAN, DEFAULT_SPAN_SIZE);
Interval vSpan = new Interval(row, row + rowSpan);
this.rowGroup = new Group(vSpan, getRowAlignment(gravity, height));
this.rowWeight = a.getFloat(ROW_WEIGHT, getDefaultWeight(height));
@@ -1915,6 +1985,8 @@
of the values for each View.
*/
private static class Bounds {
+ private static final Bounds GONE = new Bounds();
+
public int before;
public int after;
@@ -1922,20 +1994,24 @@
reset();
}
- private void reset() {
+ protected void reset() {
before = Integer.MIN_VALUE;
after = Integer.MIN_VALUE;
}
- private void include(int before, int after) {
+ protected void include(int before, int after) {
this.before = max(this.before, before);
this.after = max(this.after, after);
}
- private int size() {
+ protected int size() {
return before + after;
}
+ protected int getOffset(View c, Alignment alignment, int type, int size) {
+ return before - alignment.getAlignmentValue(c, size, type);
+ }
+
@Override
public String toString() {
return "Bounds{" +
@@ -1957,6 +2033,8 @@
* {@code x} such that {@code min <= x < max}.
*/
/* package */ static class Interval {
+ private static final Interval GONE = new Interval(UNDEFINED, UNDEFINED);
+
/**
* The minimum value.
*/
@@ -2042,6 +2120,8 @@
* {@code span} and {@code alignment}.
*/
public static class Group {
+ private static final Group GONE = new Group(Interval.GONE, Alignment.GONE);
+
/**
* The grid indices of the leading and trailing edges of this cell group for the
* appropriate axis.
@@ -2157,17 +2237,30 @@
* {@link Group#alignment alignment}. Overall placement of the view in the cell
* group is specified by the two alignments which act along each axis independently.
* <p>
- * An Alignment implementation must define {@link #getAlignmentValue(View, int, int)},
- * to return the appropriate value for the type of alignment being defined.
- * The enclosing algorithms position the children
- * so that the locations defined by the alignmnet values
- * are the same for all of the views in a group.
- * <p>
* The GridLayout class defines the most common alignments used in general layout:
* {@link #TOP}, {@link #LEFT}, {@link #BOTTOM}, {@link #RIGHT}, {@link #CENTER}, {@link
* #BASELINE} and {@link #FILL}.
*/
+ /*
+ * An Alignment implementation must define {@link #getAlignmentValue(View, int, int)},
+ * to return the appropriate value for the type of alignment being defined.
+ * The enclosing algorithms position the children
+ * so that the locations defined by the alignment values
+ * are the same for all of the views in a group.
+ * <p>
+
+ */
public static abstract class Alignment {
+ private static final Alignment GONE = new Alignment() {
+ public int getAlignmentValue(View view, int viewSize, int measurementType) {
+ assert false;
+ return 0;
+ }
+ };
+
+ /*pp*/ Alignment() {
+ }
+
/**
* Returns an alignment value. In the case of vertical alignments the value
* returned should indicate the distance from the top of the view to the
@@ -2176,11 +2269,12 @@
*
* @param view the view to which this alignment should be applied
* @param viewSize the measured size of the view
- * @param measurementType the type of measurement that should be made
+ * @param measurementType This parameter is currently unused as GridLayout only supports
+ * one type of measurement: {@link View#measure(int, int)}.
*
- * @return the alignment value
+ * @return the alignment value
*/
- public abstract int getAlignmentValue(View view, int viewSize, int measurementType);
+ /*pp*/ abstract int getAlignmentValue(View view, int viewSize, int measurementType);
/**
* Returns the size of the view specified by this alignment.
@@ -2192,13 +2286,18 @@
* @param view the view to which this alignment should be applied
* @param viewSize the measured size of the view
* @param cellSize the size of the cell into which this view will be placed
- * @param measurementType the type of measurement that should be made
+ * @param measurementType This parameter is currently unused as GridLayout only supports
+ * one type of measurement: {@link View#measure(int, int)}.
*
- * @return the aligned size
+ * @return the aligned size
*/
- public int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
+ /*pp*/ int getSizeInCell(View view, int viewSize, int cellSize, int measurementType) {
return viewSize;
}
+
+ /*pp*/ Bounds getBounds() {
+ return new Bounds();
+ }
}
private static final Alignment LEADING = new Alignment() {
@@ -2262,13 +2361,43 @@
return UNDEFINED;
}
int baseline = view.getBaseline();
- if (baseline == -1) {
- return UNDEFINED;
- } else {
- return baseline;
- }
+ return (baseline == -1) ? UNDEFINED : baseline;
}
+ @Override
+ public Bounds getBounds() {
+ return new Bounds() {
+ /*
+ In a baseline aligned row in which some components define a baseline
+ and some don't, we need a third variable to properly account for all
+ the sizes. This tracks the maximum size of all the components -
+ including those that don't define a baseline.
+ */
+ private int size;
+
+ @Override
+ protected void reset() {
+ super.reset();
+ size = 0;
+ }
+
+ @Override
+ protected void include(int before, int after) {
+ super.include(before, after);
+ size = max(size, before + after);
+ }
+
+ @Override
+ protected int size() {
+ return max(super.size(), size);
+ }
+
+ @Override
+ protected int getOffset(View c, Alignment alignment, int type, int size) {
+ return max(0, super.getOffset(c, alignment, type, size));
+ }
+ };
+ }
};
/**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 17b3bda..7c9be1e 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -35,6 +35,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import java.util.List;
@@ -692,6 +694,28 @@
awakenScrollBars();
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index e3bc946..fc8bce8 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -562,9 +562,17 @@
return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
} else if (childIndex == getChildCount()) {
return (mShowDividers & SHOW_DIVIDER_END) != 0;
- } else {
- return (mShowDividers & SHOW_DIVIDER_MIDDLE) != 0;
+ } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
+ boolean hasVisibleViewBefore = false;
+ for (int i = childIndex - 1; i >= 0; i--) {
+ if (getChildAt(i).getVisibility() != GONE) {
+ hasVisibleViewBefore = true;
+ break;
+ }
+ }
+ return hasVisibleViewBefore;
}
+ return false;
}
/**
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 2947ebe..aa23ad0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1201,18 +1201,15 @@
private void initializeScrollWheel() {
if (mInitialScrollOffset != Integer.MIN_VALUE) {
return;
-
}
int[] selectorIndices = getSelectorIndices();
int totalTextHeight = selectorIndices.length * mTextSize;
- int totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
- int textGapCount = selectorIndices.length - 1;
- int selectorTextGapHeight = totalTextGapHeight / textGapCount;
- // compensate for integer division loss of the components used to
- // calculate the text gap
- int integerDivisionLoss = (mTextSize + mBottom - mTop) % textGapCount;
- mInitialScrollOffset = mCurrentScrollOffset = mTextSize - integerDivisionLoss / 2;
+ float totalTextGapHeight = (mBottom - mTop) - totalTextHeight;
+ float textGapCount = selectorIndices.length - 1;
+ int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f);
mSelectorElementHeight = mTextSize + selectorTextGapHeight;
+ mInitialScrollOffset = mTextSize - 3 * (mSelectorElementHeight % 2);
+ mCurrentScrollOffset = mInitialScrollOffset;
updateInputTextView();
}
diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java
index 82770ad..17512d8 100644
--- a/core/java/android/widget/PopupMenu.java
+++ b/core/java/android/widget/PopupMenu.java
@@ -18,6 +18,7 @@
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.SubMenuBuilder;
import android.content.Context;
@@ -32,12 +33,25 @@
* If the IME is visible the popup will not overlap it until it is touched. Touching outside
* of the popup will dismiss it.
*/
-public class PopupMenu implements MenuBuilder.Callback {
+public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback {
private Context mContext;
private MenuBuilder mMenu;
private View mAnchor;
private MenuPopupHelper mPopup;
private OnMenuItemClickListener mMenuItemClickListener;
+ private OnDismissListener mDismissListener;
+
+ /**
+ * Callback interface used to notify the application that the menu has closed.
+ */
+ public interface OnDismissListener {
+ /**
+ * Called when the associated menu has been dismissed.
+ *
+ * @param menu The PopupMenu that was dismissed.
+ */
+ public void onDismiss(PopupMenu menu);
+ }
/**
* Construct a new PopupMenu.
@@ -53,6 +67,7 @@
mMenu.setCallback(this);
mAnchor = anchor;
mPopup = new MenuPopupHelper(context, mMenu, anchor);
+ mPopup.setCallback(this);
}
/**
@@ -77,6 +92,15 @@
}
/**
+ * Inflate a menu resource into this PopupMenu. This is equivalent to calling
+ * popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()).
+ * @param menuRes Menu resource to inflate
+ */
+ public void inflate(int menuRes) {
+ getMenuInflater().inflate(menuRes, mMenu);
+ }
+
+ /**
* Show the menu popup anchored to the view specified during construction.
* @see #dismiss()
*/
@@ -92,11 +116,25 @@
mPopup.dismiss();
}
+ /**
+ * Set a listener that will be notified when the user selects an item from the menu.
+ *
+ * @param listener Listener to notify
+ */
public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
mMenuItemClickListener = listener;
}
/**
+ * Set a listener that will be notified when this menu is dismissed.
+ *
+ * @param listener Listener to notify
+ */
+ public void setOnDismissListener(OnDismissListener listener) {
+ mDismissListener = listener;
+ }
+
+ /**
* @hide
*/
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
@@ -110,12 +148,15 @@
* @hide
*/
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ if (mDismissListener != null) {
+ mDismissListener.onDismiss(this);
+ }
}
/**
* @hide
*/
- public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
if (!subMenu.hasVisibleItems()) {
return true;
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 27edb88..12775a4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -36,6 +36,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import java.util.List;
@@ -690,6 +692,28 @@
awakenScrollBars();
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 586ece8..f3bda43 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -603,7 +603,7 @@
final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
// Should we show the close button? It is not shown if there's no focus,
// field is not iconified by default and there is no text in it.
- final boolean showClose = hasText || mIconifiedByDefault || mQueryTextView.hasFocus();
+ final boolean showClose = hasText || mIconifiedByDefault;
mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
}
@@ -919,17 +919,22 @@
}
private void onCloseClicked() {
- if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
- CharSequence text = mQueryTextView.getText();
- if (TextUtils.isEmpty(text)) {
+ CharSequence text = mQueryTextView.getText();
+ if (TextUtils.isEmpty(text)) {
+ if (mIconifiedByDefault) {
// query field already empty, hide the keyboard and remove focus
clearFocus();
setImeVisibility(false);
- } else {
- mQueryTextView.setText("");
}
+ } else {
+ mQueryTextView.setText("");
+ mQueryTextView.requestFocus();
+ setImeVisibility(true);
+ }
+
+ if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) {
updateViewsVisibility(mIconifiedByDefault);
- if (mIconifiedByDefault) setImeVisibility(false);
+ setImeVisibility(false);
}
}
diff --git a/core/java/android/widget/Space.java b/core/java/android/widget/Space.java
index d98b937..d7b2ec2 100644
--- a/core/java/android/widget/Space.java
+++ b/core/java/android/widget/Space.java
@@ -72,4 +72,35 @@
public void setLayoutParams(ViewGroup.LayoutParams params) {
super.setLayoutParams(params);
}
+
+ /**
+ * Compare to: {@link View#getDefaultSize(int, int)}
+ * If mode is AT_MOST, return the child size instead of the parent size
+ * (unless it is too big).
+ */
+ private static int getDefaultSize2(int size, int measureSpec) {
+ int result = size;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ switch (specMode) {
+ case MeasureSpec.UNSPECIFIED:
+ result = size;
+ break;
+ case MeasureSpec.AT_MOST:
+ result = Math.min(size, specSize);
+ break;
+ case MeasureSpec.EXACTLY:
+ result = specSize;
+ break;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
+ getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 02c2b8f..939779f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -340,6 +340,16 @@
private WordIterator mWordIterator;
+ // The alignment to pass to Layout, or null if not resolved.
+ private Layout.Alignment mLayoutAlignment;
+
+ // The default value for mTextAlign.
+ private TextAlign mTextAlign = TextAlign.INHERIT;
+
+ private static enum TextAlign {
+ INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
+ }
+
/*
* Kick-start the font cache for the zygote process (to pay the cost of
* initializing freetype for our default font only once).
@@ -4948,7 +4958,10 @@
if (mMovement != null && mText instanceof Editable
&& mLayout != null && onCheckIsTextEditor()) {
InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.showSoftInput(this, 0);
+ if (imm != null) {
+ imm.viewClicked(this);
+ imm.showSoftInput(this, 0);
+ }
}
}
}
@@ -5529,6 +5542,73 @@
physicalWidth, false);
}
+ @Override
+ protected void resetLayoutDirectionResolution() {
+ super.resetLayoutDirectionResolution();
+
+ if (mLayoutAlignment != null &&
+ (mTextAlign == TextAlign.VIEW_START ||
+ mTextAlign == TextAlign.VIEW_END)) {
+ mLayoutAlignment = null;
+ }
+ }
+
+ private Layout.Alignment getLayoutAlignment() {
+ if (mLayoutAlignment == null) {
+ Layout.Alignment alignment;
+ TextAlign textAlign = mTextAlign;
+ switch (textAlign) {
+ case INHERIT:
+ // fall through to gravity temporarily
+ // intention is to inherit value through view hierarchy.
+ case GRAVITY:
+ switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
+ case Gravity.START:
+ alignment = Layout.Alignment.ALIGN_NORMAL;
+ break;
+ case Gravity.END:
+ alignment = Layout.Alignment.ALIGN_OPPOSITE;
+ break;
+ case Gravity.LEFT:
+ alignment = Layout.Alignment.ALIGN_LEFT;
+ break;
+ case Gravity.RIGHT:
+ alignment = Layout.Alignment.ALIGN_RIGHT;
+ break;
+ case Gravity.CENTER_HORIZONTAL:
+ alignment = Layout.Alignment.ALIGN_CENTER;
+ break;
+ default:
+ alignment = Layout.Alignment.ALIGN_NORMAL;
+ break;
+ }
+ break;
+ case TEXT_START:
+ alignment = Layout.Alignment.ALIGN_NORMAL;
+ break;
+ case TEXT_END:
+ alignment = Layout.Alignment.ALIGN_OPPOSITE;
+ break;
+ case CENTER:
+ alignment = Layout.Alignment.ALIGN_CENTER;
+ break;
+ case VIEW_START:
+ alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+ Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_LEFT;
+ break;
+ case VIEW_END:
+ alignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+ Layout.Alignment.ALIGN_LEFT : Layout.Alignment.ALIGN_RIGHT;
+ break;
+ default:
+ alignment = Layout.Alignment.ALIGN_NORMAL;
+ break;
+ }
+ mLayoutAlignment = alignment;
+ }
+ return mLayoutAlignment;
+ }
+
/**
* The width passed in is now the desired layout width,
* not the full view width with padding.
@@ -5549,25 +5629,7 @@
hintWidth = 0;
}
- final int layoutDirection = getResolvedLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
- Layout.Alignment alignment;
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.CENTER_HORIZONTAL:
- alignment = Layout.Alignment.ALIGN_CENTER;
- break;
-
- case Gravity.RIGHT:
- // Note, Layout resolves ALIGN_OPPOSITE to left or
- // right based on the paragraph direction.
- alignment = Layout.Alignment.ALIGN_OPPOSITE;
- break;
-
- default:
- alignment = Layout.Alignment.ALIGN_NORMAL;
- }
-
+ Layout.Alignment alignment = getLayoutAlignment();
boolean shouldEllipsize = mEllipsize != null && mInput == null;
if (mText instanceof Spannable) {
@@ -6834,9 +6896,9 @@
* @param selEnd The new selection end location.
*/
protected void onSelectionChanged(int selStart, int selEnd) {
- // intentionally empty
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
}
-
+
/**
* Adds a TextWatcher to the list of those whose methods are called
* whenever this TextView's text changes.
@@ -7398,8 +7460,11 @@
if ((isTextEditable() || mTextIsSelectable) && touchIsFinished) {
// Show the IME, except when selecting in read-only text.
+ final InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null) {
+ imm.viewClicked(this);
+ }
if (!mTextIsSelectable) {
- final InputMethodManager imm = InputMethodManager.peekInstance();
handled |= imm != null && imm.showSoftInput(this, 0);
}
@@ -7658,12 +7723,17 @@
}
@Override
- public void findViewsWithText(ArrayList<View> outViews, CharSequence text) {
+ public void findViewsWithText(ArrayList<View> outViews, CharSequence searched) {
+ if (TextUtils.isEmpty(searched)) {
+ return;
+ }
CharSequence thisText = getText();
if (TextUtils.isEmpty(thisText)) {
return;
}
- if (thisText.toString().toLowerCase().contains(text)) {
+ String searchedLowerCase = searched.toString().toLowerCase();
+ String thisTextLowerCase = thisText.toString().toLowerCase();
+ if (thisTextLowerCase.contains(searchedLowerCase)) {
outViews.add(this);
}
}
@@ -7917,6 +7987,12 @@
final boolean isPassword = hasPasswordTransformationMethod();
event.setPassword(isPassword);
+
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
+ event.setFromIndex(Selection.getSelectionStart(mText));
+ event.setToIndex(Selection.getSelectionEnd(mText));
+ event.setItemCount(mText.length());
+ }
}
@Override
@@ -9999,6 +10075,127 @@
return mInBatchEditControllers;
}
+ /**
+ * Resolve the text direction.
+ *
+ * Text direction of paragraphs in a TextView is determined using a heuristic. If the correct
+ * text direction cannot be determined by the heuristic, the view’s resolved layout direction
+ * determines the direction.
+ *
+ * This heuristic and result is applied individually to each paragraph in a TextView, based on
+ * the text and style content of that paragraph. Paragraph text styles can also be used to force
+ * a particular direction.
+ */
+ @Override
+ protected void resolveTextDirection() {
+ int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+ switch(mTextDirection) {
+ default:
+ case TEXT_DIRECTION_INHERIT:
+ // Try to the text direction from the parent layout. If not possible, then we will
+ // use the default layout direction to decide later
+ if (mParent != null && mParent instanceof ViewGroup) {
+ resolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
+ }
+ break;
+ case TEXT_DIRECTION_FIRST_STRONG:
+ resolvedTextDirection = getTextDirectionFromFirstStrong(mText);
+ break;
+ case TEXT_DIRECTION_ANY_RTL:
+ resolvedTextDirection = getTextDirectionFromAnyRtl(mText);
+ break;
+ case TEXT_DIRECTION_LTR:
+ resolvedTextDirection = TEXT_DIRECTION_LTR;
+ break;
+ case TEXT_DIRECTION_RTL:
+ resolvedTextDirection = TEXT_DIRECTION_RTL;
+ break;
+ }
+ // if we have been so far unable to get the text direction from the heuristics, then we are
+ // falling back using the layout direction
+ if (resolvedTextDirection == TEXT_DIRECTION_UNDEFINED) {
+ switch(getResolvedLayoutDirection()) {
+ default:
+ case LAYOUT_DIRECTION_LTR:
+ resolvedTextDirection = TEXT_DIRECTION_LTR;
+ break;
+ case LAYOUT_DIRECTION_RTL:
+ resolvedTextDirection = TEXT_DIRECTION_RTL;
+ break;
+ }
+ }
+ mResolvedTextDirection = resolvedTextDirection;
+ }
+
+ /**
+ * Get text direction following the "first strong" heuristic.
+ *
+ * @param cs the CharSequence used to get the text direction.
+ *
+ * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+ * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+ */
+ private static int getTextDirectionFromFirstStrong(final CharSequence cs) {
+ final int length = cs.length();
+ for(int i = 0; i < length; i++) {
+ final char c = cs.charAt(i);
+ final byte dir = Character.getDirectionality(c);
+ if (isStrongLtrChar(dir)) {
+ return TEXT_DIRECTION_LTR;
+ } else if (isStrongRtlChar(dir)) {
+ return TEXT_DIRECTION_RTL;
+ }
+ }
+ return TEXT_DIRECTION_UNDEFINED;
+ }
+
+ /**
+ * Get text direction following the "any RTL" heuristic.
+ *
+ * @param cs the CharSequence used to get the text direction.
+ *
+ * @return {@link #TEXT_DIRECTION_RTL} if direction it RTL, {@link #TEXT_DIRECTION_LTR} if
+ * direction it LTR or {@link #TEXT_DIRECTION_UNDEFINED} if direction cannot be found.
+ */
+ private static int getTextDirectionFromAnyRtl(final CharSequence cs) {
+ final int length = cs.length();
+ boolean foundStrongLtr = false;
+ boolean foundStrongRtl = false;
+ for(int i = 0; i < length; i++) {
+ final char c = cs.charAt(i);
+ final byte dir = Character.getDirectionality(c);
+ if (isStrongLtrChar(dir)) {
+ foundStrongLtr = true;
+ } else if (isStrongRtlChar(dir)) {
+ foundStrongRtl = true;
+ }
+ }
+ if (foundStrongRtl) {
+ return TEXT_DIRECTION_RTL;
+ }
+ if (foundStrongLtr) {
+ return TEXT_DIRECTION_LTR;
+ }
+ return TEXT_DIRECTION_UNDEFINED;
+ }
+
+ /**
+ * Return true if the char direction is corresponding to a "strong RTL char" following the
+ * Unicode Bidirectional Algorithm (UBA).
+ */
+ private static boolean isStrongRtlChar(final byte dir) {
+ return (dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
+ dir == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC);
+ }
+
+ /**
+ * Return true if the char direction is corresponding to a "strong LTR char" following the
+ * Unicode Bidirectional Algorithm (UBA).
+ */
+ private static boolean isStrongLtrChar(final byte dir) {
+ return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT);
+ }
+
@ViewDebug.ExportedProperty(category = "text")
private CharSequence mText;
private CharSequence mTransformed;
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 8d5df6f..519acf5 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -16,7 +16,6 @@
package com.android.internal.app;
-import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPopupHelper;
import com.android.internal.view.menu.SubMenuBuilder;
@@ -36,7 +35,6 @@
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.ActionMode;
@@ -580,6 +578,9 @@
mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+ if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
+ mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
+ }
}
/**
@@ -620,6 +621,7 @@
// Clear out the context mode views after the animation finishes
mContextView.closeMode();
+
mActionMode = null;
if (mWasHiddenBeforeMode) {
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index b57046c..ec64552 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -135,6 +135,16 @@
return null;
}
+ public static String getSdFilesystem(String cid) {
+ try {
+ return getMountService().getSecureContainerFilesystemPath(cid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get container path for " + cid +
+ " with exception " + e);
+ }
+ return null;
+ }
+
public static boolean finalizeSdDir(String cid) {
try {
int rc = getMountService().finalizeSecureContainer(cid);
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 18d9ec4..773be5b 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -16,8 +16,12 @@
package com.android.internal.net;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemClock;
/**
* A simple container used to carry information in VpnBuilder, VpnDialogs,
@@ -27,6 +31,30 @@
*/
public class VpnConfig implements Parcelable {
+ public static final String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
+
+ public static void enforceCallingPackage(String packageName) {
+ if (!"com.android.vpndialogs".equals(packageName)) {
+ throw new SecurityException("Unauthorized Caller");
+ }
+ }
+
+ public static Intent getIntentForConfirmation() {
+ Intent intent = new Intent();
+ intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ConfirmDialog");
+ return intent;
+ }
+
+ public static PendingIntent getIntentForNotification(Context context, VpnConfig config) {
+ config.startTime = SystemClock.elapsedRealtime();
+ Intent intent = new Intent();
+ intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ManageDialog");
+ intent.putExtra("config", config);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
+ Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
public String packageName;
public String sessionName;
public String interfaceName;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 12687a1..7b65964 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,6 +41,7 @@
import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.TimeUtils;
import java.io.BufferedReader;
import java.io.File;
@@ -4870,8 +4871,8 @@
return 0;
}
- void readHistory(Parcel in) {
- mHistoryBaseTime = in.readLong();
+ void readHistory(Parcel in, boolean andOldHistory) {
+ final long historyBaseTime = in.readLong();
mHistoryBuffer.setDataSize(0);
mHistoryBuffer.setDataPosition(0);
@@ -4889,15 +4890,35 @@
in.setDataPosition(curPos + bufSize);
}
- long oldnow = SystemClock.elapsedRealtime() - (5*60*1000);
- if (oldnow > 0) {
- // If the system process has restarted, but not the entire
- // system, then the mHistoryBaseTime already accounts for
- // much of the elapsed time. We thus want to adjust it back,
- // to avoid large gaps in the data. We determine we are
- // in this case by arbitrarily saying it is so if at this
- // point in boot the elapsed time is already more than 5 minutes.
- mHistoryBaseTime -= oldnow;
+ if (andOldHistory) {
+ readOldHistory(in);
+ }
+
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** OLD mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ mHistoryBaseTime = historyBaseTime;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** NEW mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+
+ // We are just arbitrarily going to insert 1 minute from the sample of
+ // the last run until samples in this run.
+ if (mHistoryBaseTime > 0) {
+ long oldnow = SystemClock.elapsedRealtime();
+ mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** ADJUSTED mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
}
}
@@ -4910,12 +4931,24 @@
}
}
- void writeHistory(Parcel out) {
- out.writeLong(mLastHistoryTime);
+ void writeHistory(Parcel out, boolean andOldHistory) {
+ if (DEBUG_HISTORY) {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("****************** WRITING mHistoryBaseTime: ");
+ TimeUtils.formatDuration(mHistoryBaseTime, sb);
+ sb.append(" mLastHistoryTime: ");
+ TimeUtils.formatDuration(mLastHistoryTime, sb);
+ Slog.i(TAG, sb.toString());
+ }
+ out.writeLong(mHistoryBaseTime + mLastHistoryTime);
out.writeInt(mHistoryBuffer.dataSize());
if (DEBUG_HISTORY) Slog.i(TAG, "***************** WRITING HISTORY: "
+ mHistoryBuffer.dataSize() + " bytes at " + out.dataPosition());
out.appendFrom(mHistoryBuffer, 0, mHistoryBuffer.dataSize());
+
+ if (andOldHistory) {
+ writeOldHistory(out);
+ }
}
void writeOldHistory(Parcel out) {
@@ -4935,8 +4968,7 @@
return;
}
- readHistory(in);
- readOldHistory(in);
+ readHistory(in, true);
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
@@ -5136,8 +5168,7 @@
out.writeInt(VERSION);
- writeHistory(out);
- writeOldHistory(out);
+ writeHistory(out, true);
out.writeInt(mStartCount);
out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
@@ -5340,7 +5371,7 @@
throw new ParcelFormatException("Bad magic number");
}
- readHistory(in);
+ readHistory(in, false);
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
@@ -5461,7 +5492,7 @@
out.writeInt(MAGIC);
- writeHistory(out);
+ writeHistory(out, false);
out.writeInt(mStartCount);
out.writeLong(mBatteryUptime);
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 5e9cd23..f13e770 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -25,16 +25,13 @@
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
-
import com.android.internal.logging.AndroidConfig;
-
+import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.VMRuntime;
-
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.logging.LogManager;
import java.util.TimeZone;
-
+import java.util.logging.LogManager;
import org.apache.harmony.luni.internal.util.TimezoneGetter;
/**
@@ -129,6 +126,11 @@
System.setProperty("http.agent", userAgent);
/*
+ * Wire socket tagging to traffic stats.
+ */
+ NetworkManagementSocketTagger.install();
+
+ /*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
diff --git a/core/java/com/android/internal/util/HanziToPinyin.java b/core/java/com/android/internal/util/HanziToPinyin.java
deleted file mode 100644
index 6a4adaa..0000000
--- a/core/java/com/android/internal/util/HanziToPinyin.java
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * An object to convert Chinese character to its corresponding pinyin string.
- * For characters with multiple possible pinyin string, only one is selected
- * according to collator. Polyphone is not supported in this implementation.
- * This class is implemented to achieve the best runtime performance and minimum
- * runtime resources with tolerable sacrifice of accuracy. This implementation
- * highly depends on zh_CN ICU collation data and must be always synchronized with
- * ICU.
- */
-public class HanziToPinyin {
- private static final String TAG = "HanziToPinyin";
-
- private static final char[] UNIHANS = {
- '\u5416', '\u54ce', '\u5b89', '\u80ae', '\u51f9', '\u516b', '\u63b0', '\u6273',
- '\u90a6', '\u52f9', '\u9642', '\u5954', '\u4f3b', '\u7680', '\u782d', '\u706c',
- '\u618b', '\u6c43', '\u51ab', '\u7676', '\u5cec', '\u5693', '\u5072', '\u53c2',
- '\u4ed3', '\u64a1', '\u518a', '\u5d7e', '\u564c', '\u6260', '\u62c6', '\u8fbf',
- '\u4f25', '\u6284', '\u8f66', '\u62bb', '\u9637', '\u5403', '\u5145', '\u62bd',
- '\u51fa', '\u640b', '\u5ddb', '\u5205', '\u5439', '\u65fe', '\u8e14', '\u5472',
- '\u4ece', '\u51d1', '\u7c97', '\u6c46', '\u5d14', '\u90a8', '\u6413', '\u5491',
- '\u5446', '\u4e39', '\u5f53', '\u5200', '\u6074', '\u6265', '\u706f', '\u4efe',
- '\u55f2', '\u6541', '\u5201', '\u7239', '\u4e01', '\u4e1f', '\u4e1c', '\u543a',
- '\u5262', '\u8011', '\u5796', '\u5428', '\u591a', '\u59b8', '\u5940', '\u97a5',
- '\u800c', '\u53d1', '\u5e06', '\u531a', '\u98de', '\u5206', '\u4e30', '\u8985',
- '\u4ecf', '\u57ba', '\u7d11', '\u592b', '\u7324', '\u65ee', '\u4f85', '\u5e72',
- '\u5188', '\u768b', '\u6208', '\u7ed9', '\u6839', '\u63ef', '\u55bc', '\u55f0',
- '\u5de5', '\u52fe', '\u4f30', '\u9e39', '\u4e56', '\u5173', '\u5149', '\u5f52',
- '\u4e28', '\u8b34', '\u5459', '\u598e', '\u548d', '\u4f44', '\u592f', '\u8320',
- '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u53ff', '\u9f41', '\u4e4e', '\u82b1',
- '\u6000', '\u6b22', '\u5ddf', '\u7070', '\u660f', '\u5419', '\u4e0c', '\u52a0',
- '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u5755', '\u5182', '\u4e29',
- '\u51e5', '\u59e2', '\u5658', '\u519b', '\u5494', '\u5f00', '\u938e', '\u5ffc',
- '\u5c3b', '\u533c', '\u808e', '\u52a5', '\u7a7a', '\u62a0', '\u625d', '\u5938',
- '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764', '\u6269', '\u62c9', '\u4f86',
- '\u5170', '\u5577', '\u635e', '\u4ec2', '\u96f7', '\u8137', '\u68f1', '\u695e',
- '\u550e', '\u4fe9', '\u5afe', '\u826f', '\u8e7d', '\u57d3', '\u53b8', '\u62ce',
- '\u6e9c', '\u9f99', '\u5a04', '\u565c', '\u5b6a', '\u62a1', '\u9831', '\u5988',
- '\u57cb', '\u989f', '\u7264', '\u732b', '\u5445', '\u95e8', '\u6c13', '\u54aa',
- '\u5b80', '\u55b5', '\u4e5c', '\u6c11', '\u540d', '\u8c2c', '\u6478', '\u725f',
- '\u6bcd', '\u62cf', '\u8149', '\u56e1', '\u56d4', '\u5b6c', '\u8bb7', '\u5a1e',
- '\u5ae9', '\u80fd', '\u92b0', '\u62c8', '\u5a18', '\u9e1f', '\u634f', '\u56dc',
- '\u5b81', '\u599e', '\u519c', '\u7fba', '\u5974', '\u597b', '\u9ec1', '\u90cd',
- '\u5662', '\u8bb4', '\u5991', '\u62cd', '\u7705', '\u6c78', '\u629b', '\u5478',
- '\u55b7', '\u5309', '\u4e76', '\u7247', '\u527d', '\u6c15', '\u59d8', '\u4e52',
- '\u948b', '\u5256', '\u4ec6', '\u4e03', '\u6390', '\u5343', '\u545b', '\u6084',
- '\u5207', '\u4eb2', '\u9751', '\u5b86', '\u74d7', '\u533a', '\u5cd1', '\u7094',
- '\u590b', '\u5465', '\u7a63', '\u835b', '\u60f9', '\u4eba', '\u6254', '\u65e5',
- '\u620e', '\u53b9', '\u909a', '\u5827', '\u6875', '\u95f0', '\u633c', '\u4ee8',
- '\u6be2', '\u4e09', '\u6852', '\u63bb', '\u8272', '\u68ee', '\u50e7', '\u6740',
- '\u7b5b', '\u5c71', '\u4f24', '\u5f30', '\u5962', '\u7533', '\u5347', '\u5c38',
- '\u53ce', '\u4e66', '\u5237', '\u8870', '\u95e9', '\u53cc', '\u8c01', '\u542e',
- '\u8bf4', '\u53b6', '\u5fea', '\u51c1', '\u82cf', '\u72fb', '\u590a', '\u5b59',
- '\u5506', '\u4ed6', '\u5b61', '\u574d', '\u6c64', '\u5932', '\u5fd1', '\u81af',
- '\u5254', '\u5929', '\u65eb', '\u6017', '\u5385', '\u70b5', '\u5077', '\u51f8',
- '\u6e4d', '\u63a8', '\u541e', '\u8bac', '\u52b8', '\u6b6a', '\u5f2f', '\u5c23',
- '\u5371', '\u6637', '\u7fc1', '\u631d', '\u4e4c', '\u5915', '\u5477', '\u4ed9',
- '\u4e61', '\u7071', '\u4e9b', '\u5fc3', '\u5174', '\u51f6', '\u4f11', '\u620c',
- '\u5405', '\u75b6', '\u7025', '\u4e2b', '\u54bd', '\u592e', '\u5e7a', '\u503b',
- '\u4e00', '\u4e5a', '\u5e94', '\u5537', '\u4f63', '\u4f18', '\u7ea1', '\u56e6',
- '\u66f0', '\u8480', '\u5e00', '\u707d', '\u5142', '\u7242', '\u50ae', '\u556b',
- '\u9c61', '\u600e', '\u66fd', '\u5412', '\u635a', '\u6cbe', '\u5f20', '\u4f4b',
- '\u8707', '\u8d1e', '\u9eee', '\u4e4b', '\u4e2d', '\u5dde', '\u6731', '\u6293',
- '\u62fd', '\u4e13', '\u5986', '\u96b9', '\u5b92', '\u5353', '\u4ed4', '\u5b97',
- '\u90b9', '\u79df', '\u5297', '\u55fa', '\u5c0a', '\u6628',
- };
- private final static byte[][] PINYINS = {
- {65, 00, 00, 00, 00, 00, }, {65, 73, 00, 00, 00, 00, },
- {65, 78, 00, 00, 00, 00, }, {65, 78, 71, 00, 00, 00, },
- {65, 79, 00, 00, 00, 00, }, {66, 65, 00, 00, 00, 00, },
- {66, 65, 73, 00, 00, 00, }, {66, 65, 78, 00, 00, 00, },
- {66, 65, 78, 71, 00, 00, }, {66, 65, 79, 00, 00, 00, },
- {66, 69, 73, 00, 00, 00, }, {66, 69, 78, 00, 00, 00, },
- {66, 69, 78, 71, 00, 00, }, {66, 73, 00, 00, 00, 00, },
- {66, 73, 65, 78, 00, 00, }, {66, 73, 65, 79, 00, 00, },
- {66, 73, 69, 00, 00, 00, }, {66, 73, 78, 00, 00, 00, },
- {66, 73, 78, 71, 00, 00, }, {66, 79, 00, 00, 00, 00, },
- {66, 85, 00, 00, 00, 00, }, {67, 65, 00, 00, 00, 00, },
- {67, 65, 73, 00, 00, 00, }, {67, 65, 78, 00, 00, 00, },
- {67, 65, 78, 71, 00, 00, }, {67, 65, 79, 00, 00, 00, },
- {67, 69, 00, 00, 00, 00, }, {67, 69, 78, 00, 00, 00, },
- {67, 69, 78, 71, 00, 00, }, {67, 72, 65, 00, 00, 00, },
- {67, 72, 65, 73, 00, 00, }, {67, 72, 65, 78, 00, 00, },
- {67, 72, 65, 78, 71, 00, }, {67, 72, 65, 79, 00, 00, },
- {67, 72, 69, 00, 00, 00, }, {67, 72, 69, 78, 00, 00, },
- {67, 72, 69, 78, 71, 00, }, {67, 72, 73, 00, 00, 00, },
- {67, 72, 79, 78, 71, 00, }, {67, 72, 79, 85, 00, 00, },
- {67, 72, 85, 00, 00, 00, }, {67, 72, 85, 65, 73, 00, },
- {67, 72, 85, 65, 78, 00, }, {67, 72, 85, 65, 78, 71, },
- {67, 72, 85, 73, 00, 00, }, {67, 72, 85, 78, 00, 00, },
- {67, 72, 85, 79, 00, 00, }, {67, 73, 00, 00, 00, 00, },
- {67, 79, 78, 71, 00, 00, }, {67, 79, 85, 00, 00, 00, },
- {67, 85, 00, 00, 00, 00, }, {67, 85, 65, 78, 00, 00, },
- {67, 85, 73, 00, 00, 00, }, {67, 85, 78, 00, 00, 00, },
- {67, 85, 79, 00, 00, 00, }, {68, 65, 00, 00, 00, 00, },
- {68, 65, 73, 00, 00, 00, }, {68, 65, 78, 00, 00, 00, },
- {68, 65, 78, 71, 00, 00, }, {68, 65, 79, 00, 00, 00, },
- {68, 69, 00, 00, 00, 00, }, {68, 69, 78, 00, 00, 00, },
- {68, 69, 78, 71, 00, 00, }, {68, 73, 00, 00, 00, 00, },
- {68, 73, 65, 00, 00, 00, }, {68, 73, 65, 78, 00, 00, },
- {68, 73, 65, 79, 00, 00, }, {68, 73, 69, 00, 00, 00, },
- {68, 73, 78, 71, 00, 00, }, {68, 73, 85, 00, 00, 00, },
- {68, 79, 78, 71, 00, 00, }, {68, 79, 85, 00, 00, 00, },
- {68, 85, 00, 00, 00, 00, }, {68, 85, 65, 78, 00, 00, },
- {68, 85, 73, 00, 00, 00, }, {68, 85, 78, 00, 00, 00, },
- {68, 85, 79, 00, 00, 00, }, {69, 00, 00, 00, 00, 00, },
- {69, 78, 00, 00, 00, 00, }, {69, 78, 71, 00, 00, 00, },
- {69, 82, 00, 00, 00, 00, }, {70, 65, 00, 00, 00, 00, },
- {70, 65, 78, 00, 00, 00, }, {70, 65, 78, 71, 00, 00, },
- {70, 69, 73, 00, 00, 00, }, {70, 69, 78, 00, 00, 00, },
- {70, 69, 78, 71, 00, 00, }, {70, 73, 65, 79, 00, 00, },
- {70, 79, 00, 00, 00, 00, }, {70, 85, 00, 00, 00, 00, },
- {70, 79, 85, 00, 00, 00, }, {70, 85, 00, 00, 00, 00, },
- {71, 85, 73, 00, 00, 00, }, {71, 65, 00, 00, 00, 00, },
- {71, 65, 73, 00, 00, 00, }, {71, 65, 78, 00, 00, 00, },
- {71, 65, 78, 71, 00, 00, }, {71, 65, 79, 00, 00, 00, },
- {71, 69, 00, 00, 00, 00, }, {71, 69, 73, 00, 00, 00, },
- {71, 69, 78, 00, 00, 00, }, {71, 69, 78, 71, 00, 00, },
- {74, 73, 69, 00, 00, 00, }, {71, 69, 00, 00, 00, 00, },
- {71, 79, 78, 71, 00, 00, }, {71, 79, 85, 00, 00, 00, },
- {71, 85, 00, 00, 00, 00, }, {71, 85, 65, 00, 00, 00, },
- {71, 85, 65, 73, 00, 00, }, {71, 85, 65, 78, 00, 00, },
- {71, 85, 65, 78, 71, 00, }, {71, 85, 73, 00, 00, 00, },
- {71, 85, 78, 00, 00, 00, }, {71, 85, 65, 78, 00, 00, },
- {71, 85, 79, 00, 00, 00, }, {72, 65, 00, 00, 00, 00, },
- {72, 65, 73, 00, 00, 00, }, {72, 65, 78, 00, 00, 00, },
- {72, 65, 78, 71, 00, 00, }, {72, 65, 79, 00, 00, 00, },
- {72, 69, 00, 00, 00, 00, }, {72, 69, 73, 00, 00, 00, },
- {72, 69, 78, 00, 00, 00, }, {72, 69, 78, 71, 00, 00, },
- {72, 79, 78, 71, 00, 00, }, {72, 79, 85, 00, 00, 00, },
- {72, 85, 00, 00, 00, 00, }, {72, 85, 65, 00, 00, 00, },
- {72, 85, 65, 73, 00, 00, }, {72, 85, 65, 78, 00, 00, },
- {72, 85, 65, 78, 71, 00, }, {72, 85, 73, 00, 00, 00, },
- {72, 85, 78, 00, 00, 00, }, {72, 85, 79, 00, 00, 00, },
- {74, 73, 00, 00, 00, 00, }, {74, 73, 65, 00, 00, 00, },
- {74, 73, 65, 78, 00, 00, }, {74, 73, 65, 78, 71, 00, },
- {74, 73, 65, 79, 00, 00, }, {74, 73, 69, 00, 00, 00, },
- {74, 73, 78, 00, 00, 00, }, {74, 73, 78, 71, 00, 00, },
- {74, 73, 79, 78, 71, 00, }, {74, 73, 85, 00, 00, 00, },
- {74, 85, 00, 00, 00, 00, }, {74, 85, 65, 78, 00, 00, },
- {74, 85, 69, 00, 00, 00, }, {74, 85, 78, 00, 00, 00, },
- {75, 65, 00, 00, 00, 00, }, {75, 65, 73, 00, 00, 00, },
- {75, 65, 78, 00, 00, 00, }, {75, 65, 78, 71, 00, 00, },
- {75, 65, 79, 00, 00, 00, }, {75, 69, 00, 00, 00, 00, },
- {75, 69, 78, 00, 00, 00, }, {75, 69, 78, 71, 00, 00, },
- {75, 79, 78, 71, 00, 00, }, {75, 79, 85, 00, 00, 00, },
- {75, 85, 00, 00, 00, 00, }, {75, 85, 65, 00, 00, 00, },
- {75, 85, 65, 73, 00, 00, }, {75, 85, 65, 78, 00, 00, },
- {75, 85, 65, 78, 71, 00, }, {75, 85, 73, 00, 00, 00, },
- {75, 85, 78, 00, 00, 00, }, {75, 85, 79, 00, 00, 00, },
- {76, 65, 00, 00, 00, 00, }, {76, 65, 73, 00, 00, 00, },
- {76, 65, 78, 00, 00, 00, }, {76, 65, 78, 71, 00, 00, },
- {76, 65, 79, 00, 00, 00, }, {76, 69, 00, 00, 00, 00, },
- {76, 69, 73, 00, 00, 00, }, {76, 73, 00, 00, 00, 00, },
- {76, 73, 78, 71, 00, 00, }, {76, 69, 78, 71, 00, 00, },
- {76, 73, 00, 00, 00, 00, }, {76, 73, 65, 00, 00, 00, },
- {76, 73, 65, 78, 00, 00, }, {76, 73, 65, 78, 71, 00, },
- {76, 73, 65, 79, 00, 00, }, {76, 73, 69, 00, 00, 00, },
- {76, 73, 78, 00, 00, 00, }, {76, 73, 78, 71, 00, 00, },
- {76, 73, 85, 00, 00, 00, }, {76, 79, 78, 71, 00, 00, },
- {76, 79, 85, 00, 00, 00, }, {76, 85, 00, 00, 00, 00, },
- {76, 85, 65, 78, 00, 00, }, {76, 85, 78, 00, 00, 00, },
- {76, 85, 79, 00, 00, 00, }, {77, 65, 00, 00, 00, 00, },
- {77, 65, 73, 00, 00, 00, }, {77, 65, 78, 00, 00, 00, },
- {77, 65, 78, 71, 00, 00, }, {77, 65, 79, 00, 00, 00, },
- {77, 69, 73, 00, 00, 00, }, {77, 69, 78, 00, 00, 00, },
- {77, 69, 78, 71, 00, 00, }, {77, 73, 00, 00, 00, 00, },
- {77, 73, 65, 78, 00, 00, }, {77, 73, 65, 79, 00, 00, },
- {77, 73, 69, 00, 00, 00, }, {77, 73, 78, 00, 00, 00, },
- {77, 73, 78, 71, 00, 00, }, {77, 73, 85, 00, 00, 00, },
- {77, 79, 00, 00, 00, 00, }, {77, 79, 85, 00, 00, 00, },
- {77, 85, 00, 00, 00, 00, }, {78, 65, 00, 00, 00, 00, },
- {78, 65, 73, 00, 00, 00, }, {78, 65, 78, 00, 00, 00, },
- {78, 65, 78, 71, 00, 00, }, {78, 65, 79, 00, 00, 00, },
- {78, 69, 00, 00, 00, 00, }, {78, 69, 73, 00, 00, 00, },
- {78, 69, 78, 00, 00, 00, }, {78, 69, 78, 71, 00, 00, },
- {78, 73, 00, 00, 00, 00, }, {78, 73, 65, 78, 00, 00, },
- {78, 73, 65, 78, 71, 00, }, {78, 73, 65, 79, 00, 00, },
- {78, 73, 69, 00, 00, 00, }, {78, 73, 78, 00, 00, 00, },
- {78, 73, 78, 71, 00, 00, }, {78, 73, 85, 00, 00, 00, },
- {78, 79, 78, 71, 00, 00, }, {78, 79, 85, 00, 00, 00, },
- {78, 85, 00, 00, 00, 00, }, {78, 85, 65, 78, 00, 00, },
- {78, 85, 78, 00, 00, 00, }, {78, 85, 79, 00, 00, 00, },
- {79, 00, 00, 00, 00, 00, }, {79, 85, 00, 00, 00, 00, },
- {80, 65, 00, 00, 00, 00, }, {80, 65, 73, 00, 00, 00, },
- {80, 65, 78, 00, 00, 00, }, {80, 65, 78, 71, 00, 00, },
- {80, 65, 79, 00, 00, 00, }, {80, 69, 73, 00, 00, 00, },
- {80, 69, 78, 00, 00, 00, }, {80, 69, 78, 71, 00, 00, },
- {80, 73, 00, 00, 00, 00, }, {80, 73, 65, 78, 00, 00, },
- {80, 73, 65, 79, 00, 00, }, {80, 73, 69, 00, 00, 00, },
- {80, 73, 78, 00, 00, 00, }, {80, 73, 78, 71, 00, 00, },
- {80, 79, 00, 00, 00, 00, }, {80, 79, 85, 00, 00, 00, },
- {80, 85, 00, 00, 00, 00, }, {81, 73, 00, 00, 00, 00, },
- {81, 73, 65, 00, 00, 00, }, {81, 73, 65, 78, 00, 00, },
- {81, 73, 65, 78, 71, 00, }, {81, 73, 65, 79, 00, 00, },
- {81, 73, 69, 00, 00, 00, }, {81, 73, 78, 00, 00, 00, },
- {81, 73, 78, 71, 00, 00, }, {81, 73, 79, 78, 71, 00, },
- {81, 73, 85, 00, 00, 00, }, {81, 85, 00, 00, 00, 00, },
- {81, 85, 65, 78, 00, 00, }, {81, 85, 69, 00, 00, 00, },
- {81, 85, 78, 00, 00, 00, }, {82, 65, 78, 00, 00, 00, },
- {82, 65, 78, 71, 00, 00, }, {82, 65, 79, 00, 00, 00, },
- {82, 69, 00, 00, 00, 00, }, {82, 69, 78, 00, 00, 00, },
- {82, 69, 78, 71, 00, 00, }, {82, 73, 00, 00, 00, 00, },
- {82, 79, 78, 71, 00, 00, }, {82, 79, 85, 00, 00, 00, },
- {82, 85, 00, 00, 00, 00, }, {82, 85, 65, 78, 00, 00, },
- {82, 85, 73, 00, 00, 00, }, {82, 85, 78, 00, 00, 00, },
- {82, 85, 79, 00, 00, 00, }, {83, 65, 00, 00, 00, 00, },
- {83, 65, 73, 00, 00, 00, }, {83, 65, 78, 00, 00, 00, },
- {83, 65, 78, 71, 00, 00, }, {83, 65, 79, 00, 00, 00, },
- {83, 69, 00, 00, 00, 00, }, {83, 69, 78, 00, 00, 00, },
- {83, 69, 78, 71, 00, 00, }, {83, 72, 65, 00, 00, 00, },
- {83, 72, 65, 73, 00, 00, }, {83, 72, 65, 78, 00, 00, },
- {83, 72, 65, 78, 71, 00, }, {83, 72, 65, 79, 00, 00, },
- {83, 72, 69, 00, 00, 00, }, {83, 72, 69, 78, 00, 00, },
- {83, 72, 69, 78, 71, 00, }, {83, 72, 73, 00, 00, 00, },
- {83, 72, 79, 85, 00, 00, }, {83, 72, 85, 00, 00, 00, },
- {83, 72, 85, 65, 00, 00, }, {83, 72, 85, 65, 73, 00, },
- {83, 72, 85, 65, 78, 00, }, {83, 72, 85, 65, 78, 71, },
- {83, 72, 85, 73, 00, 00, }, {83, 72, 85, 78, 00, 00, },
- {83, 72, 85, 79, 00, 00, }, {83, 73, 00, 00, 00, 00, },
- {83, 79, 78, 71, 00, 00, }, {83, 79, 85, 00, 00, 00, },
- {83, 85, 00, 00, 00, 00, }, {83, 85, 65, 78, 00, 00, },
- {83, 85, 73, 00, 00, 00, }, {83, 85, 78, 00, 00, 00, },
- {83, 85, 79, 00, 00, 00, }, {84, 65, 00, 00, 00, 00, },
- {84, 65, 73, 00, 00, 00, }, {84, 65, 78, 00, 00, 00, },
- {84, 65, 78, 71, 00, 00, }, {84, 65, 79, 00, 00, 00, },
- {84, 69, 00, 00, 00, 00, }, {84, 69, 78, 71, 00, 00, },
- {84, 73, 00, 00, 00, 00, }, {84, 73, 65, 78, 00, 00, },
- {84, 73, 65, 79, 00, 00, }, {84, 73, 69, 00, 00, 00, },
- {84, 73, 78, 71, 00, 00, }, {84, 79, 78, 71, 00, 00, },
- {84, 79, 85, 00, 00, 00, }, {84, 85, 00, 00, 00, 00, },
- {84, 85, 65, 78, 00, 00, }, {84, 85, 73, 00, 00, 00, },
- {84, 85, 78, 00, 00, 00, }, {84, 85, 79, 00, 00, 00, },
- {87, 65, 00, 00, 00, 00, }, {87, 65, 73, 00, 00, 00, },
- {87, 65, 78, 00, 00, 00, }, {87, 65, 78, 71, 00, 00, },
- {87, 69, 73, 00, 00, 00, }, {87, 69, 78, 00, 00, 00, },
- {87, 69, 78, 71, 00, 00, }, {87, 79, 00, 00, 00, 00, },
- {87, 85, 00, 00, 00, 00, }, {88, 73, 00, 00, 00, 00, },
- {88, 73, 65, 00, 00, 00, }, {88, 73, 65, 78, 00, 00, },
- {88, 73, 65, 78, 71, 00, }, {88, 73, 65, 79, 00, 00, },
- {88, 73, 69, 00, 00, 00, }, {88, 73, 78, 00, 00, 00, },
- {88, 73, 78, 71, 00, 00, }, {88, 73, 79, 78, 71, 00, },
- {88, 73, 85, 00, 00, 00, }, {88, 85, 00, 00, 00, 00, },
- {88, 85, 65, 78, 00, 00, }, {88, 85, 69, 00, 00, 00, },
- {88, 85, 78, 00, 00, 00, }, {89, 65, 00, 00, 00, 00, },
- {89, 65, 78, 00, 00, 00, }, {89, 65, 78, 71, 00, 00, },
- {89, 65, 79, 00, 00, 00, }, {89, 69, 00, 00, 00, 00, },
- {89, 73, 00, 00, 00, 00, }, {89, 73, 78, 00, 00, 00, },
- {89, 73, 78, 71, 00, 00, }, {89, 79, 00, 00, 00, 00, },
- {89, 79, 78, 71, 00, 00, }, {89, 79, 85, 00, 00, 00, },
- {89, 85, 00, 00, 00, 00, }, {89, 85, 65, 78, 00, 00, },
- {89, 85, 69, 00, 00, 00, }, {89, 85, 78, 00, 00, 00, },
- {90, 65, 00, 00, 00, 00, }, {90, 65, 73, 00, 00, 00, },
- {90, 65, 78, 00, 00, 00, }, {90, 65, 78, 71, 00, 00, },
- {90, 65, 79, 00, 00, 00, }, {90, 69, 00, 00, 00, 00, },
- {90, 69, 73, 00, 00, 00, }, {90, 69, 78, 00, 00, 00, },
- {90, 69, 78, 71, 00, 00, }, {90, 72, 65, 00, 00, 00, },
- {90, 72, 65, 73, 00, 00, }, {90, 72, 65, 78, 00, 00, },
- {90, 72, 65, 78, 71, 00, }, {90, 72, 65, 79, 00, 00, },
- {90, 72, 69, 00, 00, 00, }, {90, 72, 69, 78, 00, 00, },
- {90, 72, 69, 78, 71, 00, }, {90, 72, 73, 00, 00, 00, },
- {90, 72, 79, 78, 71, 00, }, {90, 72, 79, 85, 00, 00, },
- {90, 72, 85, 00, 00, 00, }, {90, 72, 85, 65, 00, 00, },
- {90, 72, 85, 65, 73, 00, }, {90, 72, 85, 65, 78, 00, },
- {90, 72, 85, 65, 78, 71, }, {90, 72, 85, 73, 00, 00, },
- {90, 72, 85, 78, 00, 00, }, {90, 72, 85, 79, 00, 00, },
- {90, 73, 00, 00, 00, 00, }, {90, 79, 78, 71, 00, 00, },
- {90, 79, 85, 00, 00, 00, }, {90, 85, 00, 00, 00, 00, },
- {90, 85, 65, 78, 00, 00, }, {90, 85, 73, 00, 00, 00, },
- {90, 85, 78, 00, 00, 00, }, {90, 85, 79, 00, 00, 00, },
-
- };
-
- /** First and last Chinese character with known Pinyin according to zh collation */
- private static final String FIRST_PINYIN_UNIHAN = "\u5416";
- private static final String LAST_PINYIN_UNIHAN = "\u5497";
- /** The first Chinese character in Unicode block */
- private static final char FIRST_UNIHAN = '\u3400';
- private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA);
-
- private static HanziToPinyin sInstance;
- private final boolean mHasChinaCollator;
-
- public static class Token {
- /**
- * Separator between target string for each source char
- */
- public static final String SEPARATOR = " ";
-
- public static final int LATIN = 1;
- public static final int PINYIN = 2;
- public static final int UNKNOWN = 3;
-
- public Token() {
- }
-
- public Token(int type, String source, String target) {
- this.type = type;
- this.source = source;
- this.target = target;
- }
- /**
- * Type of this token, ASCII, PINYIN or UNKNOWN.
- */
- public int type;
- /**
- * Original string before translation.
- */
- public String source;
- /**
- * Translated string of source. For Han, target is corresponding Pinyin.
- * Otherwise target is original string in source.
- */
- public String target;
- }
-
- protected HanziToPinyin(boolean hasChinaCollator) {
- mHasChinaCollator = hasChinaCollator;
- }
-
- public static HanziToPinyin getInstance() {
- synchronized(HanziToPinyin.class) {
- if (sInstance != null) {
- return sInstance;
- }
- // Check if zh_CN collation data is available
- final Locale locale[] = Collator.getAvailableLocales();
- for (int i = 0; i < locale.length; i++) {
- if (locale[i].equals(Locale.CHINA)) {
- sInstance = new HanziToPinyin(true);
- return sInstance;
- }
- }
- Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");
- sInstance = new HanziToPinyin(false);
- return sInstance;
- }
- }
-
- private Token getToken(char character) {
- Token token = new Token();
- final String letter = Character.toString(character);
- token.source = letter;
- int offset = -1;
- int cmp;
- if (character < 256) {
- token.type = Token.LATIN;
- token.target = letter;
- return token;
- } else if (character < FIRST_UNIHAN) {
- token.type = Token.UNKNOWN;
- token.target = letter;
- return token;
- } else {
- cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN);
- if (cmp < 0) {
- token.type = Token.UNKNOWN;
- token.target = letter;
- return token;
- } else if (cmp == 0) {
- token.type = Token.PINYIN;
- offset = 0;
- } else {
- cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN);
- if (cmp > 0) {
- token.type = Token.UNKNOWN;
- token.target = letter;
- return token;
- } else if (cmp == 0) {
- token.type = Token.PINYIN;
- offset = UNIHANS.length - 1;
- }
- }
- }
-
- token.type = Token.PINYIN;
- if (offset < 0) {
- int begin = 0;
- int end = UNIHANS.length - 1;
- while (begin <= end) {
- offset = (begin + end) / 2;
- final String unihan = Character.toString(UNIHANS[offset]);
- cmp = COLLATOR.compare(letter, unihan);
- if (cmp == 0) {
- break;
- } else if (cmp > 0) {
- begin = offset + 1;
- } else {
- end = offset - 1;
- }
- }
- }
- if (cmp < 0) {
- offset--;
- }
- StringBuilder pinyin = new StringBuilder();
- for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) {
- pinyin.append((char)PINYINS[offset][j]);
- }
- token.target = pinyin.toString();
- return token;
- }
-
- /**
- * Convert the input to a array of tokens. The sequence of ASCII or Unknown
- * characters without space will be put into a Token, One Hanzi character
- * which has pinyin will be treated as a Token.
- * If these is no China collator, the empty token array is returned.
- */
- public ArrayList<Token> get(final String input) {
- ArrayList<Token> tokens = new ArrayList<Token>();
- if (!mHasChinaCollator || TextUtils.isEmpty(input)) {
- // return empty tokens.
- return tokens;
- }
- final int inputLength = input.length();
- final StringBuilder sb = new StringBuilder();
- int tokenType = Token.LATIN;
- // Go through the input, create a new token when
- // a. Token type changed
- // b. Get the Pinyin of current charater.
- // c. current character is space.
- for (int i = 0; i < inputLength; i++) {
- final char character = input.charAt(i);
- if (character == ' ') {
- if (sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- } else if (character < 256) {
- if (tokenType != Token.LATIN && sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- tokenType = Token.LATIN;
- sb.append(character);
- } else if (character < FIRST_UNIHAN) {
- if (tokenType != Token.UNKNOWN && sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- tokenType = Token.UNKNOWN;
- sb.append(character);
- } else {
- Token t = getToken(character);
- if (t.type == Token.PINYIN) {
- if (sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- tokens.add(t);
- tokenType = Token.PINYIN;
- } else {
- if (tokenType != t.type && sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- tokenType = t.type;
- sb.append(character);
- }
- }
- }
- if (sb.length() > 0) {
- addToken(sb, tokens, tokenType);
- }
- return tokens;
- }
-
- private void addToken(final StringBuilder sb, final ArrayList<Token> tokens,
- final int tokenType) {
- String str = sb.toString();
- tokens.add(new Token(tokenType, str, str));
- sb.setLength(0);
- }
-
-}
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 338dcaa..f875cbd 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -36,7 +36,9 @@
void updateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
int candidatesStart, int candidatesEnd);
-
+
+ void viewClicked(boolean focusChanged);
+
void updateCursor(in Rect newCursor);
void displayCompletions(in CompletionInfo[] completions);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 98c2747..2fec9cd 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -26,6 +26,7 @@
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.View.MeasureSpec;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ImageButton;
@@ -69,9 +70,7 @@
final Resources res = context.getResources();
if (!mReserveOverflowSet) {
- // TODO Use the no-buttons specifier instead here
- mReserveOverflow = res.getConfiguration()
- .isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
+ mReserveOverflow = !ViewConfiguration.get(context).hasPermanentMenuKey();
}
if (!mWidthLimitSet) {
@@ -336,6 +335,7 @@
if (groupId != 0) {
seenGroups.put(groupId, true);
}
+ item.setIsActionButton(true);
} else if (item.requestsActionButton()) {
// Items in a group with other items that already have an action slot
// can break the max actions rule, but not the width limit.
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index f8d24a3..27e4191 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -177,17 +177,19 @@
public void restoreHierarchyState(Bundle inState) {
SparseArray<Parcelable> viewStates = inState.getSparseParcelableArray(VIEWS_TAG);
- ((View) mMenuView).restoreHierarchyState(viewStates);
+ if (viewStates != null) {
+ ((View) mMenuView).restoreHierarchyState(viewStates);
+ }
}
private class MenuAdapter extends BaseAdapter {
public int getCount() {
- ArrayList<MenuItemImpl> items = mMenu.getVisibleItems();
+ ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
return items.size() - mItemIndexOffset;
}
public MenuItemImpl getItem(int position) {
- ArrayList<MenuItemImpl> items = mMenu.getVisibleItems();
+ ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
return items.get(position + mItemIndexOffset);
}
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 1a6cc54..253511c 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -507,7 +507,7 @@
}
public boolean isActionButton() {
- return (mFlags & IS_ACTION) == IS_ACTION || requiresActionButton();
+ return (mFlags & IS_ACTION) == IS_ACTION;
}
public boolean requestsActionButton() {
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 5767519..cffbb4e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -17,6 +17,7 @@
package com.android.internal.view.menu;
import android.content.Context;
+import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -71,8 +72,9 @@
mMenu = menu;
mOverflowOnly = overflowOnly;
- final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
- mPopupMaxWidth = metrics.widthPixels / 2;
+ final Resources res = context.getResources();
+ mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
+ res.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
mAnchorView = anchorView;
@@ -124,6 +126,7 @@
public void onDismiss() {
mPopup = null;
+ mMenu.close();
if (mTreeObserver != null) {
if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
mTreeObserver.removeGlobalOnLayoutListener(this);
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index d710cfa..953328c 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -105,24 +105,19 @@
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int nonTabHeight = 0;
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
+ if (mActionBarView == null) return;
- if (child == mTabContainer) continue;
-
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- nonTabHeight = Math.max(nonTabHeight,
- child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
- }
+ final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
+ final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
+ mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
final int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode == MeasureSpec.AT_MOST) {
final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),
- Math.min(nonTabHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+ Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
+ maxHeight));
}
}
}
@@ -137,12 +132,14 @@
if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
// Not showing home, put tabs on top.
final int count = getChildCount();
- for (int i = 0; i < count; i++){
+ for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child == mTabContainer) continue;
- child.offsetTopAndBottom(tabHeight);
+ if (!mActionBarView.isCollapsed()) {
+ child.offsetTopAndBottom(tabHeight);
+ }
}
mTabContainer.layout(l, 0, r, tabHeight);
} else {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index fc43994..3e3eeab 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -287,7 +287,7 @@
availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
}
- if (mMenuView != null) {
+ if (mMenuView != null && mMenuView.getParent() == this) {
availableWidth = measureChildView(mMenuView, availableWidth,
childSpecHeight, 0);
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 9d8d361..09bc1fc 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -96,6 +96,8 @@
private LinearLayout mTitleLayout;
private TextView mTitleView;
private TextView mSubtitleView;
+ private View mTitleUpView;
+
private Spinner mSpinner;
private LinearLayout mListNavLayout;
private ScrollingTabContainerView mTabScrollView;
@@ -115,6 +117,7 @@
private boolean mUserTitle;
private boolean mIncludeTabs;
private boolean mIsCollapsable;
+ private boolean mIsCollapsed;
private MenuBuilder mOptionsMenu;
@@ -152,6 +155,16 @@
}
};
+ private final OnClickListener mUpClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ Context context = getContext();
+ if (context instanceof Activity) {
+ Activity activity = (Activity) context;
+ activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
+ }
+ }
+ };
+
public ActionBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -230,15 +243,7 @@
a.recycle();
mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
- mHomeLayout.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- Context context = getContext();
- if (context instanceof Activity) {
- Activity activity = (Activity) context;
- activity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem);
- }
- }
- });
+ mHomeLayout.setOnClickListener(mUpClickListener);
mHomeLayout.setClickable(true);
mHomeLayout.setFocusable(true);
}
@@ -438,7 +443,8 @@
}
if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
- final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
+ final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
+ final int vis = showHome ? VISIBLE : GONE;
mHomeLayout.setVisibility(vis);
if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
@@ -458,6 +464,14 @@
}
}
+ if (mTitleLayout != null && (flagsChanged &
+ (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
+ final boolean homeAsUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
+ final boolean titleUp = homeAsUp && !showHome;
+ mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE);
+ mTitleLayout.setEnabled(titleUp);
+ }
+
if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
addView(mCustomNavView);
@@ -635,26 +649,37 @@
}
}
}
-
+
private void initTitle() {
- LayoutInflater inflater = LayoutInflater.from(getContext());
- mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
- mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
- mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
+ if (mTitleLayout == null) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ mTitleLayout = (LinearLayout) inflater.inflate(R.layout.action_bar_title_item, null);
+ mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
+ mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
+ mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
- if (mTitleStyleRes != 0) {
- mTitleView.setTextAppearance(mContext, mTitleStyleRes);
- }
- if (mTitle != null) {
- mTitleView.setText(mTitle);
- }
+ mTitleLayout.setOnClickListener(mUpClickListener);
- if (mSubtitleStyleRes != 0) {
- mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
- }
- if (mSubtitle != null) {
- mSubtitleView.setText(mSubtitle);
- mSubtitleView.setVisibility(VISIBLE);
+ if (mTitleStyleRes != 0) {
+ mTitleView.setTextAppearance(mContext, mTitleStyleRes);
+ }
+ if (mTitle != null) {
+ mTitleView.setText(mTitle);
+ }
+
+ if (mSubtitleStyleRes != 0) {
+ mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes);
+ }
+ if (mSubtitle != null) {
+ mSubtitleView.setText(mSubtitle);
+ mSubtitleView.setVisibility(VISIBLE);
+ }
+
+ final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
+ final boolean titleUp = homeAsUp &&
+ (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) == 0;
+ mTitleUpView.setVisibility(titleUp ? VISIBLE : GONE);
+ mTitleLayout.setEnabled(titleUp);
}
addView(mTitleLayout);
@@ -668,6 +693,10 @@
mIsCollapsable = collapsable;
}
+ public boolean isCollapsed() {
+ return mIsCollapsed;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int childCount = getChildCount();
@@ -684,9 +713,11 @@
if (visibleChildren == 0) {
// No size for an empty action bar when collapsable.
setMeasuredDimension(0, 0);
+ mIsCollapsed = true;
return;
}
}
+ mIsCollapsed = false;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
@@ -718,8 +749,14 @@
View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
if (homeLayout.getVisibility() != GONE) {
- homeLayout.measure(
- MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+ final LayoutParams lp = homeLayout.getLayoutParams();
+ int homeWidthSpec;
+ if (lp.width < 0) {
+ homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
+ } else {
+ homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+ }
+ homeLayout.measure(homeWidthSpec,
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
final int homeWidth = homeLayout.getMeasuredWidth();
availableWidth = Math.max(0, availableWidth - homeWidth);
@@ -734,7 +771,7 @@
if (mExpandedActionView == null) {
boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
- (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+ (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
if (showTitle) {
availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
@@ -872,7 +909,7 @@
if (mExpandedActionView == null) {
final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
- (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+ (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
if (showTitle) {
x += positionChild(mTitleLayout, x, y, contentHeight);
}
@@ -958,8 +995,8 @@
int ypos = 0;
switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
case Gravity.CENTER_VERTICAL:
- final int paddedTop = mTop + getPaddingTop();
- final int paddedBottom = mBottom - getPaddingBottom();
+ final int paddedTop = getPaddingTop();
+ final int paddedBottom = mBottom - mTop - getPaddingBottom();
ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
break;
case Gravity.TOP:
@@ -970,7 +1007,10 @@
- bottomMargin;
break;
}
- x += positionChild(customView, xpos, ypos, contentHeight);
+ final int customWidth = customView.getMeasuredWidth();
+ customView.layout(xpos, ypos, xpos + customWidth,
+ ypos + customView.getMeasuredHeight());
+ x += customWidth;
}
if (mProgressView != null) {
@@ -1096,6 +1136,34 @@
width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
height = Math.max(height,
iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
+
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ switch (widthMode) {
+ case MeasureSpec.AT_MOST:
+ width = Math.min(width, widthSize);
+ break;
+ case MeasureSpec.EXACTLY:
+ width = widthSize;
+ break;
+ case MeasureSpec.UNSPECIFIED:
+ default:
+ break;
+ }
+ switch (heightMode) {
+ case MeasureSpec.AT_MOST:
+ height = Math.min(height, heightSize);
+ break;
+ case MeasureSpec.EXACTLY:
+ height = heightSize;
+ break;
+ case MeasureSpec.UNSPECIFIED:
+ default:
+ break;
+ }
setMeasuredDimension(width, height);
}
@@ -1103,13 +1171,14 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int vCenter = (b - t) / 2;
int width = r - l;
+ int upOffset = 0;
if (mUpView.getVisibility() != GONE) {
final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
final int upHeight = mUpView.getMeasuredHeight();
final int upWidth = mUpView.getMeasuredWidth();
- final int upTop = t + vCenter - upHeight / 2;
- mUpView.layout(l, upTop, l + upWidth, upTop + upHeight);
- final int upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
+ final int upTop = vCenter - upHeight / 2;
+ mUpView.layout(0, upTop, upWidth, upTop + upHeight);
+ upOffset = upLp.leftMargin + upWidth + upLp.rightMargin;
width -= upOffset;
l += upOffset;
}
@@ -1117,8 +1186,8 @@
final int iconHeight = mIconView.getMeasuredHeight();
final int iconWidth = mIconView.getMeasuredWidth();
final int hCenter = (r - l) / 2;
- final int iconLeft = l + iconLp.leftMargin + hCenter - iconWidth / 2;
- final int iconTop = t + iconLp.topMargin + vCenter - iconHeight / 2;
+ final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2);
+ final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2);
mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
}
}
@@ -1193,7 +1262,7 @@
addView(mExpandedHomeLayout);
}
mHomeLayout.setVisibility(GONE);
- mTitleLayout.setVisibility(GONE);
+ if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
if (mSpinner != null) mSpinner.setVisibility(GONE);
if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
@@ -1210,7 +1279,11 @@
mHomeLayout.setVisibility(VISIBLE);
}
if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
- mTitleLayout.setVisibility(VISIBLE);
+ if (mTitleLayout == null) {
+ initTitle();
+ } else {
+ mTitleLayout.setVisibility(VISIBLE);
+ }
}
if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
mTabScrollView.setVisibility(VISIBLE);
diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java
index 0885b6e..ac0dc35 100644
--- a/core/java/com/android/internal/widget/DigitalClock.java
+++ b/core/java/com/android/internal/widget/DigitalClock.java
@@ -96,13 +96,13 @@
};
static class AmPm {
- private TextView mAmPm;
+ private TextView mAmPmTextView;
private String mAmString, mPmString;
AmPm(View parent, Typeface tf) {
- mAmPm = (TextView) parent.findViewById(R.id.am_pm);
- if (tf != null) {
- mAmPm.setTypeface(tf);
+ mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
+ if (mAmPmTextView != null && tf != null) {
+ mAmPmTextView.setTypeface(tf);
}
String[] ampm = new DateFormatSymbols().getAmPmStrings();
@@ -111,11 +111,15 @@
}
void setShowAmPm(boolean show) {
- mAmPm.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (mAmPmTextView != null) {
+ mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
}
void setIsMorning(boolean isMorning) {
- mAmPm.setText(isMorning ? mAmString : mPmString);
+ if (mAmPmTextView != null) {
+ mAmPmTextView.setText(isMorning ? mAmString : mPmString);
+ }
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index bee8112..97bbe52 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -103,7 +103,8 @@
private boolean mTactileFeedbackEnabled = true;
private boolean mPatternInProgress = false;
- private float mDiameterFactor = 0.5f;
+ private float mDiameterFactor = 0.10f; // TODO: move to attrs
+ private final int mStrokeAlpha = 128;
private float mHitFactor = 0.6f;
private float mSquareWidth;
@@ -131,6 +132,8 @@
private int mAspect;
private final Matrix mArrowMatrix = new Matrix();
+ private final Matrix mCircleMatrix = new Matrix();
+
/**
* Represents a cell in the 3 X 3 matrix of the unlock pattern view.
@@ -266,24 +269,29 @@
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
mPathPaint.setColor(Color.WHITE); // TODO this should be from the style
- mPathPaint.setAlpha(128);
+ mPathPaint.setAlpha(mStrokeAlpha);
mPathPaint.setStyle(Paint.Style.STROKE);
mPathPaint.setStrokeJoin(Paint.Join.ROUND);
mPathPaint.setStrokeCap(Paint.Cap.ROUND);
// lot's of bitmaps!
- mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default);
- mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched);
- mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default);
- mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green);
- mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red);
+ mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo);
+ mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo);
+ mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default_holo);
+ mBitmapCircleGreen = getBitmapFor(R.drawable.indicator_code_lock_point_area_green_holo);
+ mBitmapCircleRed = getBitmapFor(R.drawable.indicator_code_lock_point_area_red_holo);
mBitmapArrowGreenUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_green_up);
mBitmapArrowRedUp = getBitmapFor(R.drawable.indicator_code_lock_drag_direction_red_up);
- // we assume all bitmaps have the same size
- mBitmapWidth = mBitmapBtnDefault.getWidth();
- mBitmapHeight = mBitmapBtnDefault.getHeight();
+ // bitmaps have the size of the largest bitmap in this group
+ final Bitmap bitmaps[] = { mBitmapBtnDefault, mBitmapBtnTouched, mBitmapCircleDefault,
+ mBitmapCircleGreen, mBitmapCircleRed };
+
+ for (Bitmap bitmap : bitmaps) {
+ mBitmapWidth = Math.max(mBitmapWidth, bitmap.getWidth());
+ mBitmapHeight = Math.max(mBitmapHeight, bitmap.getHeight());
+ }
// allow vibration pattern to be customized
mVibePattern = loadVibratePattern(com.android.internal.R.array.config_virtualKeyVibePattern);
@@ -464,25 +472,33 @@
}
@Override
+ protected int getSuggestedMinimumWidth() {
+ // View should be large enough to contain 3 side-by-side target bitmaps
+ return 3 * mBitmapWidth;
+ }
+
+ @Override
+ protected int getSuggestedMinimumHeight() {
+ // View should be large enough to contain 3 side-by-side target bitmaps
+ return 3 * mBitmapWidth;
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = 3 * mBitmapCircleDefault.getWidth();
- final int minimumHeight = 3 * mBitmapCircleDefault.getHeight();
+ final int minimumWidth = getSuggestedMinimumWidth();
+ final int minimumHeight = getSuggestedMinimumHeight();
int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
- int requestedWidth = MeasureSpec.getSize(widthMeasureSpec);
- int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
switch (mAspect) {
case ASPECT_SQUARE:
- viewWidth = viewHeight = Math.min(requestedWidth, requestedHeight);
+ viewWidth = viewHeight = Math.min(viewWidth, viewHeight);
break;
case ASPECT_LOCK_WIDTH:
- viewWidth = requestedWidth;
- viewHeight = Math.min(requestedWidth, requestedHeight);
+ viewHeight = Math.min(viewWidth, viewHeight);
break;
case ASPECT_LOCK_HEIGHT:
- viewWidth = Math.min(requestedWidth, requestedHeight);
- viewHeight = requestedHeight;
+ viewWidth = Math.min(viewWidth, viewHeight);
break;
}
// Log.v(TAG, "LockPatternView dimensions: " + viewWidth + "x" + viewHeight);
@@ -603,178 +619,20 @@
}
@Override
- public boolean onTouchEvent(MotionEvent motionEvent) {
+ public boolean onTouchEvent(MotionEvent event) {
if (!mInputEnabled || !isEnabled()) {
return false;
}
- final float x = motionEvent.getX();
- final float y = motionEvent.getY();
- Cell hitCell;
- switch(motionEvent.getAction()) {
+ switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
- resetPattern();
- hitCell = detectAndAddHit(x, y);
- if (hitCell != null && mOnPatternListener != null) {
- mPatternInProgress = true;
- mPatternDisplayMode = DisplayMode.Correct;
- mOnPatternListener.onPatternStart();
- } else if (mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternCleared();
- }
- if (hitCell != null) {
- final float startX = getCenterXForColumn(hitCell.column);
- final float startY = getCenterYForRow(hitCell.row);
-
- final float widthOffset = mSquareWidth / 2f;
- final float heightOffset = mSquareHeight / 2f;
-
- invalidate((int) (startX - widthOffset), (int) (startY - heightOffset),
- (int) (startX + widthOffset), (int) (startY + heightOffset));
- }
- mInProgressX = x;
- mInProgressY = y;
- if (PROFILE_DRAWING) {
- if (!mDrawingProfilingStarted) {
- Debug.startMethodTracing("LockPatternDrawing");
- mDrawingProfilingStarted = true;
- }
- }
+ handleActionDown(event);
return true;
case MotionEvent.ACTION_UP:
- // report pattern detected
- if (!mPattern.isEmpty() && mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternDetected(mPattern);
- invalidate();
- }
- if (PROFILE_DRAWING) {
- if (mDrawingProfilingStarted) {
- Debug.stopMethodTracing();
- mDrawingProfilingStarted = false;
- }
- }
+ handleActionUp(event);
return true;
case MotionEvent.ACTION_MOVE:
- final int patternSizePreHitDetect = mPattern.size();
- hitCell = detectAndAddHit(x, y);
- final int patternSize = mPattern.size();
- if (hitCell != null && (mOnPatternListener != null) && (patternSize == 1)) {
- mPatternInProgress = true;
- mOnPatternListener.onPatternStart();
- }
- // note current x and y for rubber banding of in progress
- // patterns
- final float dx = Math.abs(x - mInProgressX);
- final float dy = Math.abs(y - mInProgressY);
- if (dx + dy > mSquareWidth * 0.01f) {
- float oldX = mInProgressX;
- float oldY = mInProgressY;
-
- mInProgressX = x;
- mInProgressY = y;
-
- if (mPatternInProgress && patternSize > 0) {
- final ArrayList<Cell> pattern = mPattern;
- final float radius = mSquareWidth * mDiameterFactor * 0.5f;
-
- final Cell lastCell = pattern.get(patternSize - 1);
-
- float startX = getCenterXForColumn(lastCell.column);
- float startY = getCenterYForRow(lastCell.row);
-
- float left;
- float top;
- float right;
- float bottom;
-
- final Rect invalidateRect = mInvalidate;
-
- if (startX < x) {
- left = startX;
- right = x;
- } else {
- left = x;
- right = startX;
- }
-
- if (startY < y) {
- top = startY;
- bottom = y;
- } else {
- top = y;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the current location
- invalidateRect.set((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the previous location
- invalidateRect.union((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- // Invalidate between the pattern's new cell and the pattern's previous cell
- if (hitCell != null) {
- startX = getCenterXForColumn(hitCell.column);
- startY = getCenterYForRow(hitCell.row);
-
- if (patternSize >= 2) {
- // (re-using hitcell for old cell)
- hitCell = pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
- oldX = getCenterXForColumn(hitCell.column);
- oldY = getCenterYForRow(hitCell.row);
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
- } else {
- left = right = startX;
- top = bottom = startY;
- }
-
- final float widthOffset = mSquareWidth / 2f;
- final float heightOffset = mSquareHeight / 2f;
-
- invalidateRect.set((int) (left - widthOffset),
- (int) (top - heightOffset), (int) (right + widthOffset),
- (int) (bottom + heightOffset));
- }
-
- invalidate(invalidateRect);
- } else {
- invalidate();
- }
- }
+ handleActionMove(event);
return true;
case MotionEvent.ACTION_CANCEL:
resetPattern();
@@ -793,6 +651,181 @@
return false;
}
+ private void handleActionMove(MotionEvent event) {
+ // Handle all recent motion events so we don't skip any cells even when the device
+ // is busy...
+ final int historySize = event.getHistorySize();
+ for (int i = 0; i < historySize + 1; i++) {
+ final float x = i < historySize ? event.getHistoricalX(i) : event.getX();
+ final float y = i < historySize ? event.getHistoricalY(i) : event.getY();
+ final int patternSizePreHitDetect = mPattern.size();
+ Cell hitCell = detectAndAddHit(x, y);
+ final int patternSize = mPattern.size();
+ if (hitCell != null && (mOnPatternListener != null) && (patternSize == 1)) {
+ mPatternInProgress = true;
+ mOnPatternListener.onPatternStart();
+ }
+ // note current x and y for rubber banding of in progress patterns
+ final float dx = Math.abs(x - mInProgressX);
+ final float dy = Math.abs(y - mInProgressY);
+ if (dx + dy > mSquareWidth * 0.01f) {
+ float oldX = mInProgressX;
+ float oldY = mInProgressY;
+
+ mInProgressX = x;
+ mInProgressY = y;
+
+ if (mPatternInProgress && patternSize > 0) {
+ final ArrayList<Cell> pattern = mPattern;
+ final float radius = mSquareWidth * mDiameterFactor * 0.5f;
+
+ final Cell lastCell = pattern.get(patternSize - 1);
+
+ float startX = getCenterXForColumn(lastCell.column);
+ float startY = getCenterYForRow(lastCell.row);
+
+ float left;
+ float top;
+ float right;
+ float bottom;
+
+ final Rect invalidateRect = mInvalidate;
+
+ if (startX < x) {
+ left = startX;
+ right = x;
+ } else {
+ left = x;
+ right = startX;
+ }
+
+ if (startY < y) {
+ top = startY;
+ bottom = y;
+ } else {
+ top = y;
+ bottom = startY;
+ }
+
+ // Invalidate between the pattern's last cell and the current location
+ invalidateRect.set((int) (left - radius), (int) (top - radius),
+ (int) (right + radius), (int) (bottom + radius));
+
+ if (startX < oldX) {
+ left = startX;
+ right = oldX;
+ } else {
+ left = oldX;
+ right = startX;
+ }
+
+ if (startY < oldY) {
+ top = startY;
+ bottom = oldY;
+ } else {
+ top = oldY;
+ bottom = startY;
+ }
+
+ // Invalidate between the pattern's last cell and the previous location
+ invalidateRect.union((int) (left - radius), (int) (top - radius),
+ (int) (right + radius), (int) (bottom + radius));
+
+ // Invalidate between the pattern's new cell and the pattern's previous cell
+ if (hitCell != null) {
+ startX = getCenterXForColumn(hitCell.column);
+ startY = getCenterYForRow(hitCell.row);
+
+ if (patternSize >= 2) {
+ // (re-using hitcell for old cell)
+ hitCell = pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
+ oldX = getCenterXForColumn(hitCell.column);
+ oldY = getCenterYForRow(hitCell.row);
+
+ if (startX < oldX) {
+ left = startX;
+ right = oldX;
+ } else {
+ left = oldX;
+ right = startX;
+ }
+
+ if (startY < oldY) {
+ top = startY;
+ bottom = oldY;
+ } else {
+ top = oldY;
+ bottom = startY;
+ }
+ } else {
+ left = right = startX;
+ top = bottom = startY;
+ }
+
+ final float widthOffset = mSquareWidth / 2f;
+ final float heightOffset = mSquareHeight / 2f;
+
+ invalidateRect.set((int) (left - widthOffset),
+ (int) (top - heightOffset), (int) (right + widthOffset),
+ (int) (bottom + heightOffset));
+ }
+
+ invalidate(invalidateRect);
+ } else {
+ invalidate();
+ }
+ }
+ }
+ }
+
+ private void handleActionUp(MotionEvent event) {
+ // report pattern detected
+ if (!mPattern.isEmpty() && mOnPatternListener != null) {
+ mPatternInProgress = false;
+ mOnPatternListener.onPatternDetected(mPattern);
+ invalidate();
+ }
+ if (PROFILE_DRAWING) {
+ if (mDrawingProfilingStarted) {
+ Debug.stopMethodTracing();
+ mDrawingProfilingStarted = false;
+ }
+ }
+ }
+
+ private void handleActionDown(MotionEvent event) {
+ resetPattern();
+ final float x = event.getX();
+ final float y = event.getY();
+ final Cell hitCell = detectAndAddHit(x, y);
+ if (hitCell != null && mOnPatternListener != null) {
+ mPatternInProgress = true;
+ mPatternDisplayMode = DisplayMode.Correct;
+ mOnPatternListener.onPatternStart();
+ } else if (mOnPatternListener != null) {
+ mPatternInProgress = false;
+ mOnPatternListener.onPatternCleared();
+ }
+ if (hitCell != null) {
+ final float startX = getCenterXForColumn(hitCell.column);
+ final float startY = getCenterYForRow(hitCell.row);
+
+ final float widthOffset = mSquareWidth / 2f;
+ final float heightOffset = mSquareHeight / 2f;
+
+ invalidate((int) (startX - widthOffset), (int) (startY - heightOffset),
+ (int) (startX + widthOffset), (int) (startY + heightOffset));
+ }
+ mInProgressX = x;
+ mInProgressY = y;
+ if (PROFILE_DRAWING) {
+ if (!mDrawingProfilingStarted) {
+ Debug.startMethodTracing("LockPatternDrawing");
+ mDrawingProfilingStarted = true;
+ }
+ }
+ }
+
private float getCenterXForColumn(int column) {
return mPaddingLeft + column * mSquareWidth + mSquareWidth / 2f;
}
@@ -858,11 +891,48 @@
final Path currentPath = mCurrentPath;
currentPath.rewind();
+ // draw the circles
+ final int paddingTop = mPaddingTop;
+ final int paddingLeft = mPaddingLeft;
+
+ for (int i = 0; i < 3; i++) {
+ float topY = paddingTop + i * squareHeight;
+ //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
+ for (int j = 0; j < 3; j++) {
+ float leftX = paddingLeft + j * squareWidth;
+ drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
+ }
+ }
+
// TODO: the path should be created and cached every time we hit-detect a cell
// only the last segment of the path should be computed here
// draw the path of the pattern (unless the user is in progress, and
// we are in stealth mode)
final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
+
+ // draw the arrows associated with the path (unless the user is in progress, and
+ // we are in stealth mode)
+ boolean oldFlag = (mPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
+ mPaint.setFilterBitmap(true); // draw with higher quality since we render with transforms
+ if (drawPath) {
+ for (int i = 0; i < count - 1; i++) {
+ Cell cell = pattern.get(i);
+ Cell next = pattern.get(i + 1);
+
+ // only draw the part of the pattern stored in
+ // the lookup table (this is only different in the case
+ // of animation).
+ if (!drawLookup[next.row][next.column]) {
+ break;
+ }
+
+ float leftX = paddingLeft + cell.column * squareWidth;
+ float topY = paddingTop + cell.row * squareHeight;
+
+ drawArrow(canvas, leftX, topY, cell, next);
+ }
+ }
+
if (drawPath) {
boolean anyCircles = false;
for (int i = 0; i < count; i++) {
@@ -893,41 +963,6 @@
canvas.drawPath(currentPath, mPathPaint);
}
- // draw the circles
- final int paddingTop = mPaddingTop;
- final int paddingLeft = mPaddingLeft;
-
- for (int i = 0; i < 3; i++) {
- float topY = paddingTop + i * squareHeight;
- //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
- for (int j = 0; j < 3; j++) {
- float leftX = paddingLeft + j * squareWidth;
- drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
- }
- }
-
- // draw the arrows associated with the path (unless the user is in progress, and
- // we are in stealth mode)
- boolean oldFlag = (mPaint.getFlags() & Paint.FILTER_BITMAP_FLAG) != 0;
- mPaint.setFilterBitmap(true); // draw with higher quality since we render with transforms
- if (drawPath) {
- for (int i = 0; i < count - 1; i++) {
- Cell cell = pattern.get(i);
- Cell next = pattern.get(i + 1);
-
- // only draw the part of the pattern stored in
- // the lookup table (this is only different in the case
- // of animation).
- if (!drawLookup[next.row][next.column]) {
- break;
- }
-
- float leftX = paddingLeft + cell.column * squareWidth;
- float topY = paddingTop + cell.row * squareHeight;
-
- drawArrow(canvas, leftX, topY, cell, next);
- }
- }
mPaint.setFilterBitmap(oldFlag); // restore default flag
}
@@ -947,8 +982,8 @@
// This assumes that the arrow image is drawn at 12:00 with it's top edge
// coincident with the circle bitmap's top edge.
Bitmap arrow = green ? mBitmapArrowGreenUp : mBitmapArrowRedUp;
- final int cellWidth = mBitmapCircleDefault.getWidth();
- final int cellHeight = mBitmapCircleDefault.getHeight();
+ final int cellWidth = mBitmapWidth;
+ final int cellHeight = mBitmapHeight;
// the up arrow bitmap is at 12:00, so find the rotation from x axis and add 90 degrees.
final float theta = (float) Math.atan2(
@@ -956,7 +991,12 @@
final float angle = (float) Math.toDegrees(theta) + 90.0f;
// compose matrix
+ float sx = Math.min(mSquareWidth / mBitmapWidth, 1.0f);
+ float sy = Math.min(mSquareHeight / mBitmapHeight, 1.0f);
mArrowMatrix.setTranslate(leftX + offsetX, topY + offsetY); // transform to cell position
+ mArrowMatrix.preTranslate(mBitmapWidth/2, mBitmapHeight/2);
+ mArrowMatrix.preScale(sx, sy);
+ mArrowMatrix.preTranslate(-mBitmapWidth/2, -mBitmapHeight/2);
mArrowMatrix.preRotate(angle, cellWidth / 2.0f, cellHeight / 2.0f); // rotate about cell center
mArrowMatrix.preTranslate((cellWidth - arrow.getWidth()) / 2.0f, 0.0f); // translate to 12:00 pos
canvas.drawBitmap(arrow, mArrowMatrix, mPaint);
@@ -1002,8 +1042,17 @@
int offsetX = (int) ((squareWidth - width) / 2f);
int offsetY = (int) ((squareHeight - height) / 2f);
- canvas.drawBitmap(outerCircle, leftX + offsetX, topY + offsetY, mPaint);
- canvas.drawBitmap(innerCircle, leftX + offsetX, topY + offsetY, mPaint);
+ // Allow circles to shrink if the view is too small to hold them.
+ float sx = Math.min(mSquareWidth / mBitmapWidth, 1.0f);
+ float sy = Math.min(mSquareHeight / mBitmapHeight, 1.0f);
+
+ mCircleMatrix.setTranslate(leftX + offsetX, topY + offsetY);
+ mCircleMatrix.preTranslate(mBitmapWidth/2, mBitmapHeight/2);
+ mCircleMatrix.preScale(sx, sy);
+ mCircleMatrix.preTranslate(-mBitmapWidth/2, -mBitmapHeight/2);
+
+ canvas.drawBitmap(outerCircle, mCircleMatrix, mPaint);
+ canvas.drawBitmap(innerCircle, mCircleMatrix, mPaint);
}
@Override
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5b4d7ab..2f7adf0 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,6 +15,9 @@
*/
package com.android.internal.widget;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
import android.app.ActionBar;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -22,6 +25,7 @@
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -35,6 +39,13 @@
int mMaxTabWidth;
+ protected Animator mVisibilityAnim;
+ protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
+
+ private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
+
+ private static final int FADE_DURATION = 200;
+
public ScrollingTabContainerView(Context context) {
super(context);
setHorizontalScrollBarEnabled(false);
@@ -76,6 +87,30 @@
}
}
+ public void animateToVisibility(int visibility) {
+ if (mVisibilityAnim != null) {
+ mVisibilityAnim.cancel();
+ }
+ if (visibility == VISIBLE) {
+ if (getVisibility() != VISIBLE) {
+ setAlpha(0);
+ }
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
+ anim.setDuration(FADE_DURATION);
+ anim.setInterpolator(sAlphaInterpolator);
+
+ anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ anim.start();
+ } else {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
+ anim.setDuration(FADE_DURATION);
+ anim.setInterpolator(sAlphaInterpolator);
+
+ anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+ anim.start();
+ }
+ }
+
public void animateToTab(int position) {
final View tabView = mTabLayout.getChildAt(position);
if (mTabSelector != null) {
@@ -259,4 +294,38 @@
}
}
}
+
+ protected class VisibilityAnimListener implements Animator.AnimatorListener {
+ private boolean mCanceled = false;
+ private int mFinalVisibility;
+
+ public VisibilityAnimListener withFinalVisibility(int visibility) {
+ mFinalVisibility = visibility;
+ return this;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ setVisibility(VISIBLE);
+ mVisibilityAnim = animation;
+ mCanceled = false;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCanceled) return;
+
+ mVisibilityAnim = null;
+ setVisibility(mFinalVisibility);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCanceled = true;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 1e98827..04bb689 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -20,7 +20,7 @@
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
-import android.animation.ObjectAnimator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -43,9 +43,9 @@
* A special widget containing a center and outer ring. Moving the center ring to the outer ring
* causes an event that can be caught by implementing OnTriggerListener.
*/
-public class MultiWaveView extends View implements AnimatorUpdateListener {
+public class MultiWaveView extends View {
private static final String TAG = "MultiWaveView";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
// Wave state machine
private static final int STATE_IDLE = 0;
@@ -67,14 +67,15 @@
}
// Tune-able parameters
- private static final int CHEVRON_INCREMENTAL_DELAY = 50;
- private static final int CHEVRON_ANIMATION_DURATION = 1000;
- private static final int RETURN_TO_HOME_DURATION = 150;
- private static final int HIDE_ANIMATION_DELAY = 500;
- private static final int HIDE_ANIMATION_DURACTION = 2000;
+ private static final int CHEVRON_INCREMENTAL_DELAY = 160;
+ private static final int CHEVRON_ANIMATION_DURATION = 650;
+ private static final int RETURN_TO_HOME_DELAY = 1200;
+ private static final int RETURN_TO_HOME_DURATION = 300;
+ private static final int HIDE_ANIMATION_DELAY = 200;
+ private static final int HIDE_ANIMATION_DURATION = RETURN_TO_HOME_DELAY;
private static final int SHOW_ANIMATION_DURATION = 0;
private static final int SHOW_ANIMATION_DELAY = 0;
- private TimeInterpolator mChevronAnimationInterpolator = Ease.Quint.easeOut;
+ private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
@@ -99,14 +100,31 @@
private float mHitRadius = 0.0f;
private float mSnapMargin = 0.0f;
private boolean mDragging;
+ private int mNewTargetResources;
- private AnimatorListener mResetListener = new Animator.AnimatorListener() {
- public void onAnimationStart(Animator animation) { }
- public void onAnimationRepeat(Animator animation) { }
- public void onAnimationEnd(Animator animation) {
+ private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animator) {
switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
}
- public void onAnimationCancel(Animator animation) { }
+ };
+
+ private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ invalidateGlobalRegion(mHandleDrawable);
+ invalidate();
+ }
+ };
+
+ private boolean mAnimatingTargets;
+ private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animator) {
+ if (mNewTargetResources != 0) {
+ internalSetTargetResources(mNewTargetResources);
+ mNewTargetResources = 0;
+ hideTargets(false);
+ }
+ mAnimatingTargets = false;
+ }
};
public MultiWaveView(Context context) {
@@ -135,31 +153,23 @@
mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable));
// Read chevron animation drawables
- Drawable leftChevron = a.getDrawable(R.styleable.MultiWaveView_leftChevronDrawable);
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(
- leftChevron != null ? new TargetDrawable(res, leftChevron) : null);
- }
- Drawable rightChevron = a.getDrawable(R.styleable.MultiWaveView_rightChevronDrawable);
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(
- rightChevron != null ? new TargetDrawable(res, rightChevron) : null);
- }
- Drawable topChevron = a.getDrawable(R.styleable.MultiWaveView_topChevronDrawable);
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(
- topChevron != null ? new TargetDrawable(res, topChevron) : null);
- }
- Drawable bottomChevron = a.getDrawable(R.styleable.MultiWaveView_bottomChevronDrawable);
- for (int i = 0; i < mFeedbackCount; i++) {
- mChevronDrawables.add(
- bottomChevron != null ? new TargetDrawable(res, bottomChevron) : null);
+ final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable,
+ R.styleable.MultiWaveView_rightChevronDrawable,
+ R.styleable.MultiWaveView_topChevronDrawable,
+ R.styleable.MultiWaveView_bottomChevronDrawable
+ };
+ for (int chevron : chevrons) {
+ Drawable chevronDrawable = a.getDrawable(chevron);
+ for (int i = 0; i < mFeedbackCount; i++) {
+ mChevronDrawables.add(
+ chevronDrawable != null ? new TargetDrawable(res, chevronDrawable) : null);
+ }
}
// Read array of target drawables
TypedValue outValue = new TypedValue();
if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
- setTargetResources(outValue.resourceId);
+ internalSetTargetResources(outValue.resourceId);
}
if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
throw new IllegalStateException("Must specify at least one target drawable");
@@ -205,7 +215,7 @@
case STATE_FIRST_TOUCH:
stopHandleAnimation();
deactivateTargets();
- showTargets();
+ showTargets(true);
mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
setGrabbedState(OnTriggerListener.CENTER_HANDLE);
break;
@@ -224,21 +234,22 @@
/**
* Animation used to attract user's attention to the target button.
- * Assumes mChevronDrawables is an a list with an even number of chevrons filled with left
- * followed by right chevrons.
+ * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
+ * mFeedbackCount items in the order: left, right, top, bottom.
*/
private void startChevronAnimation() {
- final float r = mHandleDrawable.getWidth() / 2;
+ final float r = mHandleDrawable.getWidth() * 0.4f;
+ final float chevronAnimationDistance = mOuterRadius * 0.8f;
final float from[][] = {
{mWaveCenterX - r, mWaveCenterY}, // left
{mWaveCenterX + r, mWaveCenterY}, // right
{mWaveCenterX, mWaveCenterY - r}, // top
{mWaveCenterX, mWaveCenterY + r} }; // bottom
final float to[][] = {
- {mWaveCenterX - mOuterRadius, mWaveCenterY}, // left
- {mWaveCenterX + mOuterRadius, mWaveCenterY}, // right
- {mWaveCenterX, mWaveCenterY - mOuterRadius}, // top
- {mWaveCenterX, mWaveCenterY + mOuterRadius} }; // bottom
+ {mWaveCenterX - chevronAnimationDistance, mWaveCenterY}, // left
+ {mWaveCenterX + chevronAnimationDistance, mWaveCenterY}, // right
+ {mWaveCenterX, mWaveCenterY - chevronAnimationDistance}, // top
+ {mWaveCenterX, mWaveCenterY + chevronAnimationDistance} }; // bottom
mChevronAnimations.clear();
for (int direction = 0; direction < 4; direction++) {
@@ -254,7 +265,7 @@
"x", new float[] { from[direction][0], to[direction][0] },
"y", new float[] { from[direction][1], to[direction][1] },
"alpha", new float[] {1.0f, 0.0f},
- "onUpdate", this));
+ "onUpdate", mUpdateListener));
}
}
}
@@ -308,70 +319,109 @@
}
private void doFinish() {
- // Inform listener of any active targets. Typically only one will be active.
final int activeTarget = mActiveTarget;
boolean targetHit = activeTarget != -1;
- if (targetHit) {
- Log.v(TAG, "Finish with target hit = " + targetHit);
- dispatchTriggerEvent(mActiveTarget);
- }
-
- setGrabbedState(OnTriggerListener.NO_HANDLE);
-
- // Animate finger outline back to home position
- mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
- mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
- "ease", Ease.Quart.easeOut,
- "delay", targetHit ? HIDE_ANIMATION_DELAY : 0,
- "alpha", 1.0f,
- "x", mWaveCenterX,
- "y", mWaveCenterY,
- "onUpdate", this,
- "onComplete", mResetListener);
// Hide unselected targets
hideTargets(true);
// Highlight the selected one
+ mHandleDrawable.setAlpha(targetHit ? 0.0f : 1.0f);
if (targetHit) {
mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+
+ hideUnselected(activeTarget);
+
+ // Inform listener of any active targets. Typically only one will be active.
+ if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+ dispatchTriggerEvent(mActiveTarget);
+ mHandleAnimation = Tweener.to(mHandleDrawable, 0,
+ "ease", Ease.Quart.easeOut,
+ "delay", RETURN_TO_HOME_DELAY,
+ "alpha", 1.0f,
+ "x", mWaveCenterX,
+ "y", mWaveCenterY,
+ "onUpdate", mUpdateListener,
+ "onComplete", mResetListener);
+ } else {
+ // Animate finger outline back to home position
+ mHandleAnimation = Tweener.to(mHandleDrawable, RETURN_TO_HOME_DURATION,
+ "ease", Ease.Quart.easeOut,
+ "delay", 0,
+ "alpha", 1.0f,
+ "x", mWaveCenterX,
+ "y", mWaveCenterY,
+ "onUpdate", mUpdateListener,
+ "onComplete", mResetListener);
}
+
+ setGrabbedState(OnTriggerListener.NO_HANDLE);
+ }
+
+ private void hideUnselected(int active) {
+ for (int i = 0; i < mTargetDrawables.size(); i++) {
+ if (i != active) {
+ mTargetDrawables.get(i).setAlpha(0.0f);
+ }
+ }
+ mOuterRing.setAlpha(0.0f);
}
private void hideTargets(boolean animate) {
if (mTargetAnimations.size() > 0) {
stopTargetAnimation();
}
- for (TargetDrawable target : mTargetDrawables) {
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target,
- animate ? HIDE_ANIMATION_DURACTION : 0,
+ // Note: these animations should complete at the same time so that we can swap out
+ // the target assets asynchronously from the setTargetResources() call.
+ mAnimatingTargets = animate;
+ if (animate) {
+ final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
+ for (TargetDrawable target : mTargetDrawables) {
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ mTargetAnimations.add(Tweener.to(target, duration,
+ "alpha", 0.0f,
+ "delay", HIDE_ANIMATION_DELAY,
+ "onUpdate", mUpdateListener));
+ }
+ mTargetAnimations.add(Tweener.to(mOuterRing, duration,
"alpha", 0.0f,
"delay", HIDE_ANIMATION_DELAY,
- "onUpdate", this));
+ "onUpdate", mUpdateListener,
+ "onComplete", mTargetUpdateListener));
+ } else {
+ for (TargetDrawable target : mTargetDrawables) {
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ target.setAlpha(0.0f);
+ }
+ mOuterRing.setAlpha(0.0f);
}
- mTargetAnimations.add(Tweener.to(mOuterRing,
- animate ? HIDE_ANIMATION_DURACTION : 0,
- "alpha", 0.0f,
- "delay", HIDE_ANIMATION_DELAY,
- "onUpdate", this));
}
- private void showTargets() {
+ private void showTargets(boolean animate) {
if (mTargetAnimations.size() > 0) {
stopTargetAnimation();
}
- for (TargetDrawable target : mTargetDrawables) {
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+ mAnimatingTargets = animate;
+ if (animate) {
+ for (TargetDrawable target : mTargetDrawables) {
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ mTargetAnimations.add(Tweener.to(target, SHOW_ANIMATION_DURATION,
+ "alpha", 1.0f,
+ "delay", SHOW_ANIMATION_DELAY,
+ "onUpdate", mUpdateListener));
+ }
+ mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
"alpha", 1.0f,
"delay", SHOW_ANIMATION_DELAY,
- "onUpdate", this));
+ "onUpdate", mUpdateListener,
+ "onComplete", mTargetUpdateListener));
+ } else {
+ for (TargetDrawable target : mTargetDrawables) {
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ target.setAlpha(1.0f);
+ }
+ mOuterRing.setAlpha(1.0f);
}
- mTargetAnimations.add(Tweener.to(mOuterRing, SHOW_ANIMATION_DURATION,
- "alpha", 1.0f,
- "delay", SHOW_ANIMATION_DELAY,
- "onUpdate", this));
}
private void stopTargetAnimation() {
@@ -387,12 +437,7 @@
}
}
- /**
- * Loads an array of drawables from the given resourceId.
- *
- * @param resourceId
- */
- public void setTargetResources(int resourceId) {
+ private void internalSetTargetResources(int resourceId) {
Resources res = getContext().getResources();
TypedArray array = res.obtainTypedArray(resourceId);
int count = array.length();
@@ -402,6 +447,21 @@
targetDrawables.add(new TargetDrawable(res, drawable));
}
mTargetDrawables = targetDrawables;
+ updateTargetPositions();
+ }
+
+ /**
+ * Loads an array of drawables from the given resourceId.
+ *
+ * @param resourceId
+ */
+ public void setTargetResources(int resourceId) {
+ if (mAnimatingTargets) {
+ // postpone this change until we return to the initial state
+ mNewTargetResources = resourceId;
+ } else {
+ internalSetTargetResources(resourceId);
+ }
}
/**
@@ -442,6 +502,7 @@
mHandleDrawable.setX(mWaveCenterX);
mHandleDrawable.setY(mWaveCenterY);
mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+ Tweener.reset();
}
@Override
@@ -449,27 +510,25 @@
final int action = event.getAction();
boolean handled = false;
- float x = event.getX();
- float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
- handleDown(x, y);
+ handleDown(event);
handled = true;
break;
case MotionEvent.ACTION_MOVE:
- handleMove(x, y);
+ handleMove(event);
handled = true;
break;
case MotionEvent.ACTION_UP:
- handleUp(x, y);
- handleMove(x, y);
+ handleMove(event);
+ handleUp(event);
handled = true;
break;
case MotionEvent.ACTION_CANCEL:
- handleMove(x, y);
+ handleMove(event);
handled = true;
break;
}
@@ -483,7 +542,9 @@
mHandleDrawable.setY(y);
}
- private void handleDown(float x, float y) {
+ private void handleDown(MotionEvent event) {
+ final float x = event.getX();
+ final float y = event.getY();
final float dx = x - mWaveCenterX;
final float dy = y - mWaveCenterY;
if (dist2(dx,dy) <= square(mTapRadius)) {
@@ -498,66 +559,72 @@
}
}
- private void handleUp(float x, float y) {
+ private void handleUp(MotionEvent event) {
if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
- switchToState(STATE_FINISH, x, y);
+ switchToState(STATE_FINISH, event.getX(), event.getY());
}
- private void handleMove(float x, float y) {
+ private void handleMove(MotionEvent event) {
if (!mDragging) {
return;
}
- float tx = x - mWaveCenterX;
- float ty = y - mWaveCenterY;
- float touchRadius = (float) Math.sqrt(dist2(tx, ty));
- final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
- float limitX = mWaveCenterX + tx * scale;
- float limitY = mWaveCenterY + ty * scale;
-
int activeTarget = -1;
- boolean singleTarget = mTargetDrawables.size() == 1;
- if (singleTarget) {
- // Snap to outer ring if there's only one target
- float snapRadius = mOuterRadius - mSnapMargin;
- if (touchRadius > snapRadius) {
- activeTarget = 0;
+ final int historySize = event.getHistorySize();
+ for (int k = 0; k < historySize + 1; k++) {
+ float x = k < historySize ? event.getHistoricalX(k) : event.getX();
+ float y = k < historySize ? event.getHistoricalY(k) : event.getY();
+ float tx = x - mWaveCenterX;
+ float ty = y - mWaveCenterY;
+ float touchRadius = (float) Math.sqrt(dist2(tx, ty));
+ final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
+ float limitX = mWaveCenterX + tx * scale;
+ float limitY = mWaveCenterY + ty * scale;
+
+ boolean singleTarget = mTargetDrawables.size() == 1;
+ if (singleTarget) {
+ // Snap to outer ring if there's only one target
+ float snapRadius = mOuterRadius - mSnapMargin;
+ if (touchRadius > snapRadius) {
+ activeTarget = 0;
+ x = limitX;
+ y = limitY;
+ }
+ } else {
+ // If there's more than one target, snap to the closest one less than hitRadius away.
+ float best = Float.MAX_VALUE;
+ final float hitRadius2 = mHitRadius * mHitRadius;
+ for (int i = 0; i < mTargetDrawables.size(); i++) {
+ // Snap to the first target in range
+ TargetDrawable target = mTargetDrawables.get(i);
+ float dx = limitX - target.getX();
+ float dy = limitY - target.getY();
+ float dist2 = dx*dx + dy*dy;
+ if (target.isValid() && dist2 < hitRadius2 && dist2 < best) {
+ activeTarget = i;
+ best = dist2;
+ }
+ }
x = limitX;
y = limitY;
}
- } else {
- // If there's more than one target, snap to the closest one less than hitRadius away.
- float best = Float.MAX_VALUE;
- final float hitRadius2 = mHitRadius * mHitRadius;
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- // Snap to the first target in range
- TargetDrawable target = mTargetDrawables.get(i);
- float dx = limitX - target.getX();
- float dy = limitY - target.getY();
- float dist2 = dx*dx + dy*dy;
- if (target.isValid() && dist2 < hitRadius2 && dist2 < best) {
- activeTarget = i;
- best = dist2;
+ if (activeTarget != -1) {
+ switchToState(STATE_SNAP, x,y);
+ float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();
+ float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();
+ moveHandleTo(newX, newY, false);
+ TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);
+ if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {
+ currentTarget.setState(TargetDrawable.STATE_FOCUSED);
+ mHandleDrawable.setAlpha(0.0f);
}
+ } else {
+ switchToState(STATE_TRACKING, x, y);
+ moveHandleTo(x, y, false);
+ mHandleDrawable.setAlpha(1.0f);
}
- x = limitX;
- y = limitY;
}
- if (activeTarget != -1) {
- switchToState(STATE_SNAP, x,y);
- float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();
- float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();
- moveHandleTo(newX, newY, false);
- TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);
- if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {
- currentTarget.setState(TargetDrawable.STATE_FOCUSED);
- mHandleDrawable.setAlpha(0.0f);
- }
- } else {
- switchToState(STATE_TRACKING, x, y);
- moveHandleTo(x, y, false);
- mHandleDrawable.setAlpha(1.0f);
- }
+
// Draw handle outside parent's bounds
invalidateGlobalRegion(mHandleDrawable);
@@ -583,20 +650,9 @@
}
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
-
- mWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
- mWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
- moveHandleTo(mWaveCenterX, mWaveCenterY, false);
- mOuterRing.setX(mWaveCenterX);
- mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
- mOuterRing.setAlpha(0.0f);
+ private void performInitialLayout(float centerX, float centerY) {
if (mOuterRadius == 0.0f) {
- mOuterRadius = 0.5f*(float) Math.sqrt(dist2(mWaveCenterX, mWaveCenterY));
+ mOuterRadius = 0.5f*(float) Math.sqrt(dist2(centerX, centerY));
}
if (mHitRadius == 0.0f) {
// Use the radius of inscribed circle of the first target.
@@ -606,6 +662,35 @@
mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
}
+ hideChevrons();
+ hideTargets(false);
+ moveHandleTo(centerX, centerY, false);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ final int width = right - left;
+ final int height = bottom - top;
+ float newWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
+ float newWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
+ if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY) {
+ if (mWaveCenterX == 0 && mWaveCenterY == 0) {
+ performInitialLayout(newWaveCenterX, newWaveCenterY);
+ }
+ mWaveCenterX = newWaveCenterX;
+ mWaveCenterY = newWaveCenterY;
+
+ mOuterRing.setX(mWaveCenterX);
+ mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
+
+ updateTargetPositions();
+ }
+ if (DEBUG) dump();
+ }
+
+ private void updateTargetPositions() {
+ // Reposition the target drawables if the view changed.
for (int i = 0; i < mTargetDrawables.size(); i++) {
final TargetDrawable targetIcon = mTargetDrawables.get(i);
double angle = -2.0f * Math.PI * i / mTargetDrawables.size();
@@ -613,11 +698,7 @@
float yPosition = mWaveCenterY + mOuterRadius * (float) Math.sin(angle);
targetIcon.setX(xPosition);
targetIcon.setY(yPosition);
- targetIcon.setAlpha(0.0f);
}
- hideChevrons();
- hideTargets(false);
- if (DEBUG) dump();
}
private void hideChevrons() {
@@ -648,11 +729,6 @@
mOnTriggerListener = listener;
}
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidateGlobalRegion(mHandleDrawable);
- invalidate();
- }
-
private float square(float d) {
return d * d;
}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index 0cff00a..bc8a62f 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -18,25 +18,42 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
import android.animation.Animator.AnimatorListener;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.util.Log;
class Tweener {
private static final String TAG = "Tweener";
+ private static final boolean DEBUG = false;
- private Object object;
ObjectAnimator animator;
private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
- public Tweener(Object obj, ObjectAnimator anim) {
- object = obj;
+ public Tweener(ObjectAnimator anim) {
animator = anim;
}
+ private static void remove(Animator animator) {
+ Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry<Object, Tweener> entry = iter.next();
+ if (entry.getValue().animator == animator) {
+ if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
+ + " sTweens.size() = " + sTweens.size());
+ iter.remove();
+ break; // an animator can only be attached to one object
+ }
+ }
+ }
+
public static Tweener to(Object object, long duration, Object... vars) {
long delay = 0;
AnimatorUpdateListener updateListener = null;
@@ -77,32 +94,35 @@
// Re-use existing tween, if present
Tweener tween = sTweens.get(object);
+ ObjectAnimator anim = null;
if (tween == null) {
- ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(object,
+ anim = ObjectAnimator.ofPropertyValuesHolder(object,
props.toArray(new PropertyValuesHolder[props.size()]));
- tween = new Tweener(object, anim);
+ tween = new Tweener(anim);
sTweens.put(object, tween);
+ if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
} else {
- tween.animator.cancel();
- replace(props, object);
+ anim = sTweens.get(object).animator;
+ replace(props, object); // Cancel all animators for given object
}
if (interpolator != null) {
- tween.animator.setInterpolator(interpolator);
+ anim.setInterpolator(interpolator);
}
// Update animation with properties discovered in loop above
- tween.animator.setStartDelay(delay);
- tween.animator.setDuration(duration);
+ anim.setStartDelay(delay);
+ anim.setDuration(duration);
if (updateListener != null) {
- tween.animator.removeAllUpdateListeners(); // There should be only one
- tween.animator.addUpdateListener(updateListener);
+ anim.removeAllUpdateListeners(); // There should be only one
+ anim.addUpdateListener(updateListener);
}
if (listener != null) {
- tween.animator.removeAllListeners(); // There should be only one.
- tween.animator.addListener(listener);
+ anim.removeAllListeners(); // There should be only one.
+ anim.addListener(listener);
}
- tween.animator.start();
+ anim.addListener(mCleanupListener);
+ anim.start();
return tween;
}
@@ -114,18 +134,40 @@
return Tweener.to(object, duration, vars);
}
- static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
+ // Listener to watch for completed animations and remove them.
+ private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ remove(animation);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ remove(animation);
+ }
+ };
+
+ public static void reset() {
+ if (DEBUG) {
+ Log.v(TAG, "Reset()");
+ if (sTweens.size() > 0) {
+ Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
+ }
+ }
+ sTweens.clear();
+ }
+
+ private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
for (final Object killobject : args) {
Tweener tween = sTweens.get(killobject);
if (tween != null) {
- if (killobject == tween.object) {
- tween.animator.cancel();
- if (props != null) {
- tween.animator.setValues(
- props.toArray(new PropertyValuesHolder[props.size()]));
- } else {
- sTweens.remove(tween);
- }
+ tween.animator.cancel();
+ if (props != null) {
+ tween.animator.setValues(
+ props.toArray(new PropertyValuesHolder[props.size()]));
+ } else {
+ sTweens.remove(tween);
}
}
}
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
new file mode 100644
index 0000000..306d223
--- /dev/null
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -0,0 +1,165 @@
+/*
+ * 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.server;
+
+import dalvik.system.SocketTagger;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.SocketException;
+import java.nio.charset.Charsets;
+
+/**
+ * Assigns tags to sockets for traffic stats.
+ */
+public final class NetworkManagementSocketTagger extends SocketTagger {
+
+ private static final boolean LOGI = false;
+
+ private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
+ @Override protected SocketTags initialValue() {
+ return new SocketTags();
+ }
+ };
+
+ public static void install() {
+ SocketTagger.set(new NetworkManagementSocketTagger());
+ }
+
+ public static void setThreadSocketStatsTag(int tag) {
+ threadSocketTags.get().statsTag = tag;
+ }
+
+ public static void setThreadSocketStatsUid(int uid) {
+ threadSocketTags.get().statsUid = uid;
+ }
+
+ @Override public void tag(FileDescriptor fd) throws SocketException {
+ final SocketTags options = threadSocketTags.get();
+ if (LOGI) {
+ System.logI("tagSocket(" + fd.getInt$() + ") with statsTag="
+ + options.statsTag + ", statsUid=" + options.statsUid);
+ }
+ try {
+ // TODO: skip tagging when options would be no-op
+ tagSocketFd(fd, options.statsTag, options.statsUid);
+ } catch (IOException e) {
+ throw new SocketException("Problem tagging socket", e);
+ }
+ }
+
+ private void tagSocketFd(FileDescriptor fd, int tag, int uid) throws IOException {
+ final int fdNum = fd.getInt$();
+ if (fdNum == -1 || (tag == -1 && uid == -1)) return;
+
+ String cmd = "t " + fdNum;
+ if (tag == -1) {
+ // Case where just the uid needs adjusting. But probably the caller
+ // will want to track his own name here, just in case.
+ cmd += " 0";
+ } else {
+ cmd += " " + tagToKernel(tag);
+ }
+ if (uid != -1) {
+ cmd += " " + uid;
+ }
+ internalModuleCtrl(cmd);
+ }
+
+ @Override public void untag(FileDescriptor fd) throws SocketException {
+ if (LOGI) {
+ System.logI("untagSocket(" + fd.getInt$() + ")");
+ }
+ try {
+ unTagSocketFd(fd);
+ } catch (IOException e) {
+ throw new SocketException("Problem untagging socket", e);
+ }
+ }
+
+ private void unTagSocketFd(FileDescriptor fd) throws IOException {
+ int fdNum = fd.getInt$();
+ if (fdNum == -1) return;
+ String cmd = "u " + fdNum;
+ internalModuleCtrl(cmd);
+ }
+
+ public static class SocketTags {
+ public int statsTag = -1;
+ public int statsUid = -1;
+ }
+
+ /**
+ * Sends commands to the kernel netfilter module.
+ *
+ * @param cmd command string for the qtaguid netfilter module. May not be null.
+ * <p>Supports:
+ * <ul><li>tag a socket:<br>
+ * <code>t <i>sock_fd</i> <i>acct_tag</i> [<i>uid_in_case_caller_is_acting_on_behalf_of</i>]</code><br>
+ * <code>*_tag</code> defaults to default_policy_tag_from_uid(uid_of_caller)<br>
+ * <code>acct_tag</code> is either 0 or greater that 2^32.<br>
+ * <code>uid_*</code> is only settable by privileged UIDs (DownloadManager,...)
+ * </li>
+ * <li>untag a socket, preserving counters:<br>
+ * <code>u <i>sock_fd</i></code>
+ * </li></ul>
+ * <p>Notes:<br>
+ * <ul><li><i>sock_fd</i> is withing the callers process space.</li>
+ * <li><i>*_tag</i> are 64bit values</li></ul>
+ *
+ */
+ private void internalModuleCtrl(String cmd) throws IOException {
+ final FileOutputStream procOut;
+ // TODO: Use something like
+ // android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
+ // to see if tagging should happen or not.
+ try {
+ procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
+ } catch (FileNotFoundException e) {
+ if (LOGI) {
+ System.logI("Can't talk to kernel module:" + e);
+ }
+ return;
+ }
+ try {
+ procOut.write(cmd.getBytes(Charsets.US_ASCII));
+ } finally {
+ procOut.close();
+ }
+ }
+
+ /**
+ * Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
+ * base-10 format like {@code 2147483647}. Currently strips signed bit to
+ * avoid using {@link java.math.BigInteger}.
+ */
+ public static String tagToKernel(int tag) {
+ // TODO: eventually write in hex, since that's what proc exports
+ // TODO: migrate to direct integer instead of odd shifting
+ return Long.toString((((long) tag) << 32) & 0x7FFFFFFF00000000L);
+ }
+
+ /**
+ * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+ * format like {@code 0x7fffffff00000000}.
+ */
+ public static int kernelToTag(String string) {
+ // TODO: migrate to direct integer instead of odd shifting
+ return (int) (Long.decode(string) >> 32);
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 7b0882f..63fa504 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -75,7 +75,6 @@
android_nio_utils.cpp \
android_nfc_NdefMessage.cpp \
android_nfc_NdefRecord.cpp \
- android_pim_EventRecurrence.cpp \
android_text_format_Time.cpp \
android_util_AssetManager.cpp \
android_util_Binder.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 21b0a42c..a61217a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -131,7 +131,6 @@
extern int register_android_nio_utils(JNIEnv* env);
extern int register_android_nfc_NdefMessage(JNIEnv *env);
extern int register_android_nfc_NdefRecord(JNIEnv *env);
-extern int register_android_pim_EventRecurrence(JNIEnv* env);
extern int register_android_text_format_Time(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
@@ -1103,7 +1102,6 @@
REG_JNI(register_android_util_Log),
REG_JNI(register_android_util_FloatMath),
REG_JNI(register_android_text_format_Time),
- REG_JNI(register_android_pim_EventRecurrence),
REG_JNI(register_android_content_AssetManager),
REG_JNI(register_android_content_StringBlock),
REG_JNI(register_android_content_XmlBlock),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 1b22e2d..18bd754 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -273,7 +273,8 @@
// These must match the int values in Bitmap.java
enum JavaEncodeFormat {
kJPEG_JavaEncodeFormat = 0,
- kPNG_JavaEncodeFormat = 1
+ kPNG_JavaEncodeFormat = 1,
+ kWEBP_JavaEncodeFormat = 2
};
static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,
@@ -288,6 +289,9 @@
case kPNG_JavaEncodeFormat:
fm = SkImageEncoder::kPNG_Type;
break;
+ case kWEBP_JavaEncodeFormat:
+ fm = SkImageEncoder::kWEBP_Type;
+ break;
default:
return false;
}
diff --git a/core/jni/android/graphics/ParcelSurfaceTexture.cpp b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
index 40966e1..754485f 100644
--- a/core/jni/android/graphics/ParcelSurfaceTexture.cpp
+++ b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
@@ -17,9 +17,11 @@
#define LOG_TAG "ParcelSurfaceTexture"
#include <gui/SurfaceTextureClient.h>
+#include <surfaceflinger/Surface.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <android_runtime/android_view_Surface.h>
#include <utils/Log.h>
@@ -96,7 +98,16 @@
}
}
-static void ParcelSurfaceTexture_init(JNIEnv* env, jobject thiz, jobject jSurfaceTexture)
+static void ParcelSurfaceTexture_initFromSurface(
+ JNIEnv* env, jobject thiz, jobject jSurface)
+{
+ sp<Surface> surface(Surface_getSurface(env, jSurface));
+ sp<ISurfaceTexture> iSurfaceTexture(surface->getSurfaceTexture());
+ ParcelSurfaceTexture_setISurfaceTexture(env, thiz, iSurfaceTexture);
+}
+
+static void ParcelSurfaceTexture_initFromSurfaceTexture(
+ JNIEnv* env, jobject thiz, jobject jSurfaceTexture)
{
sp<ISurfaceTexture> iSurfaceTexture(
SurfaceTexture_getSurfaceTexture(env, jSurfaceTexture));
@@ -131,8 +142,10 @@
static JNINativeMethod gParcelSurfaceTextureMethods[] = {
{"nativeClassInit", "()V", (void*)ParcelSurfaceTexture_classInit },
- {"nativeInit", "(Landroid/graphics/SurfaceTexture;)V",
- (void *)ParcelSurfaceTexture_init },
+ {"nativeInitFromSurface", "(Landroid/view/Surface;)V",
+ (void *)ParcelSurfaceTexture_initFromSurface },
+ {"nativeInitFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
+ (void *)ParcelSurfaceTexture_initFromSurfaceTexture },
{ "nativeFinalize", "()V", (void *)ParcelSurfaceTexture_finalize },
{ "nativeWriteToParcel", "(Landroid/os/Parcel;I)V",
(void *)ParcelSurfaceTexture_writeToParcel },
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 3f922f6..2de0932 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -91,6 +91,9 @@
virtual void onFrameAvailable();
private:
+ static JNIEnv* getJNIEnv(bool* needsDetach);
+ static void detachJNI();
+
jobject mWeakThiz;
jclass mClazz;
};
@@ -101,17 +104,57 @@
mClazz((jclass)env->NewGlobalRef(clazz))
{}
+JNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) {
+ *needsDetach = false;
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->AttachCurrentThread(&env, (void*) &args);
+ if (result != JNI_OK) {
+ LOGE("thread attach failed: %#x", result);
+ return NULL;
+ }
+ *needsDetach = true;
+ }
+ return env;
+}
+
+void JNISurfaceTextureContext::detachJNI() {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->DetachCurrentThread();
+ if (result != JNI_OK) {
+ LOGE("thread detach failed: %#x", result);
+ }
+}
+
JNISurfaceTextureContext::~JNISurfaceTextureContext()
{
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->DeleteGlobalRef(mWeakThiz);
- env->DeleteGlobalRef(mClazz);
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->DeleteGlobalRef(mWeakThiz);
+ env->DeleteGlobalRef(mClazz);
+ } else {
+ LOGW("leaking JNI object references");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
}
void JNISurfaceTextureContext::onFrameAvailable()
{
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+ } else {
+ LOGW("onFrameAvailable event will not posted");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
}
// ----------------------------------------------------------------------------
@@ -133,9 +176,9 @@
}
static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
- jobject weakThiz)
+ jobject weakThiz, jboolean allowSynchronous)
{
- sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+ sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName, allowSynchronous));
if (surfaceTexture == 0) {
jniThrowException(env, OutOfResourcesException,
"Unable to create native SurfaceTexture");
@@ -194,12 +237,12 @@
static JNINativeMethod gSurfaceTextureMethods[] = {
{"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
- {"nativeInit", "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init },
+ {"nativeInit", "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
{"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
{"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
{"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
{"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
- {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }
+ {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp },
};
int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index a5b2006..6a13876 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -461,12 +461,30 @@
Vector<GlyphRun> glyphRuns;
jchar* runGlyphs;
size_t runGlyphsCount = 0;
- size_t runIndex = 0;
+ int32_t end = start + count;
for (size_t i = 0; i < rc; ++i) {
int32_t startRun;
int32_t lengthRun;
UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
+ if (startRun >= end) {
+ break;
+ }
+
+ int32_t endRun = startRun + lengthRun;
+ if (endRun <= start) {
+ continue;
+ }
+
+ if (startRun < start) {
+ startRun = start;
+ }
+ if (endRun > end) {
+ endRun = end;
+ }
+
+ lengthRun = endRun - startRun;
+
int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
jfloat runTotalAdvance = 0;
#if DEBUG_GLYPHS
@@ -475,11 +493,10 @@
#endif
computeRunValuesWithHarfbuzz(paint, chars, startRun,
lengthRun, contextCount, newFlags,
- outAdvances + runIndex, &runTotalAdvance,
+ outAdvances, &runTotalAdvance,
&runGlyphs, &runGlyphsCount);
- runIndex += lengthRun;
-
+ outAdvances += lengthRun;
*outTotalAdvance += runTotalAdvance;
*outGlyphsCount += runGlyphsCount;
#if DEBUG_GLYPHS
diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp
index 6ae3e35..5c6f5e8 100644
--- a/core/jni/android_bluetooth_common.cpp
+++ b/core/jni/android_bluetooth_common.cpp
@@ -81,6 +81,16 @@
{"UUID", DBUS_TYPE_STRING},
};
+static Properties health_device_properties[] = {
+ {"MainChannel", DBUS_TYPE_OBJECT_PATH},
+};
+
+static Properties health_channel_properties[] = {
+ {"Type", DBUS_TYPE_STRING},
+ {"Device", DBUS_TYPE_OBJECT_PATH},
+ {"Application", DBUS_TYPE_OBJECT_PATH},
+};
+
typedef union {
char *str_val;
int int_val;
@@ -315,6 +325,22 @@
return ret;
}
+jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply) {
+
+ DBusError err;
+ jint ret = -1;
+
+ dbus_error_init(&err);
+ if (!dbus_message_get_args(reply, &err,
+ DBUS_TYPE_UNIX_FD, &ret,
+ DBUS_TYPE_INVALID)) {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+ }
+ dbus_message_unref(reply);
+ return ret;
+}
+
+
jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) {
DBusError err;
@@ -486,6 +512,55 @@
dbus_message_iter_close_container(iter, &value_iter);
}
+static void dict_append_entry(DBusMessageIter *dict,
+ const char *key, int type, void *val)
+{
+ DBusMessageIter dict_entry;
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &dict_entry);
+
+ dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
+ append_variant(&dict_entry, type, val);
+ dbus_message_iter_close_container(dict, &dict_entry);
+}
+
+static void append_dict_valist(DBusMessageIter *iterator, const char *first_key,
+ va_list var_args)
+{
+ DBusMessageIter dict;
+ int val_type;
+ const char *val_key;
+ void *val;
+
+ dbus_message_iter_open_container(iterator, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+ val_key = first_key;
+ while (val_key) {
+ val_type = va_arg(var_args, int);
+ val = va_arg(var_args, void *);
+ dict_append_entry(&dict, val_key, val_type, val);
+ val_key = va_arg(var_args, char *);
+ }
+
+ dbus_message_iter_close_container(iterator, &dict);
+}
+
+void append_dict_args(DBusMessage *reply, const char *first_key, ...)
+{
+ DBusMessageIter iter;
+ va_list var_args;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ va_start(var_args, first_key);
+ append_dict_valist(&iter, first_key, var_args);
+ va_end(var_args);
+}
+
+
int get_property(DBusMessageIter iter, Properties *properties,
int max_num_properties, int *prop_index, property_value *value, int *len) {
DBusMessageIter prop_val, array_val_iter;
@@ -737,6 +812,21 @@
sizeof(input_properties) / sizeof(Properties));
}
+jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter) {
+ return parse_properties(env, iter, (Properties *) &health_device_properties,
+ sizeof(health_device_properties) / sizeof(Properties));
+}
+
+jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg) {
+ return parse_property_change(env, msg, (Properties *) &health_device_properties,
+ sizeof(health_device_properties) / sizeof(Properties));
+}
+
+jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter) {
+ return parse_properties(env, iter, (Properties *) &health_channel_properties,
+ sizeof(health_channel_properties) / sizeof(Properties));
+}
+
int get_bdaddr(const char *str, bdaddr_t *ba) {
char *d = ((char *)ba) + 5, *endp;
int i;
diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h
index 3364703..2f5fd5a 100644
--- a/core/jni/android_bluetooth_common.h
+++ b/core/jni/android_bluetooth_common.h
@@ -149,6 +149,7 @@
jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply);
jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply);
+jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply);
jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply);
jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply);
jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply);
@@ -164,8 +165,13 @@
jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg);
jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg);
jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter);
+jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter);
+jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter);
jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg);
jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg);
+jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg);
+
+void append_dict_args(DBusMessage *reply, const char *first_key, ...);
void append_variant(DBusMessageIter *iter, int type, void *val);
int get_bdaddr(const char *str, bdaddr_t *ba);
void get_bdaddr_as_string(const bdaddr_t *ba, char *str);
diff --git a/core/jni/android_pim_EventRecurrence.cpp b/core/jni/android_pim_EventRecurrence.cpp
deleted file mode 100644
index 44e898d..0000000
--- a/core/jni/android_pim_EventRecurrence.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/* //device/libs/android_runtime/android_pim_EventRecurrence.cpp
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <pim/EventRecurrence.h>
-#include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include <utils/String8.h>
-
-namespace android {
-
-struct cached_array_fields_t
-{
- jfieldID array;
- jfieldID count;
-};
-
-static jfieldID freq_field;
-static jfieldID until_field;
-static jfieldID count_field;
-static jfieldID interval_field;
-static jfieldID wkst_field;
-static cached_array_fields_t bysecond_fields;
-static cached_array_fields_t byminute_fields;
-static cached_array_fields_t byhour_fields;
-static cached_array_fields_t byday_fields;
-static cached_array_fields_t bydayNum_fields;
-static cached_array_fields_t bymonthday_fields;
-static cached_array_fields_t byyearday_fields;
-static cached_array_fields_t byweekno_fields;
-static cached_array_fields_t bymonth_fields;
-static cached_array_fields_t bysetpos_fields;
-
-static status_t
-set_array(JNIEnv* env, int inCount, int* inArray,
- jobject This, const cached_array_fields_t& fields)
-{
- if (inCount > 0) {
- jintArray array = (jintArray) env->GetObjectField(This, fields.array);
- if (array == NULL || env->GetArrayLength(array) < inCount) {
- // +4 because it's cheap to allocate a little extra here, and
- // that reduces the chance that we'll come back here again
- array = env->NewIntArray(inCount+4);
- env->SetObjectField(This, fields.array, array);
- }
- if (array == NULL) {
- return NO_MEMORY;
- }
- env->SetIntArrayRegion(array, 0, inCount, inArray);
-
- }
- env->SetIntField(This, fields.count, inCount);
- return NO_ERROR;
-}
-
-/*
- * In class android.pim.EventRecurrence
- * public native int parse(String str);
- */
-#define SET_ARRAY_AND_CHECK(name) \
- /*printf("setting " #name " to %d elements\n", er.name##Count);*/ \
- if (set_array(env, er.name##Count, er.name, This, name##_fields) \
- != NO_ERROR) { \
- jniThrowException(env, "java/lang/RuntimeException", \
- "EventRecurrence.parse error setting field " #name " or " \
- #name "Count."); \
- return ; \
- }
-static void
-EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)
-{
- if (jstr == NULL) {
- jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");
- return ;
- }
- const jchar* jchars = env->GetStringChars(jstr, NULL);
- jsize len = env->GetStringLength(jstr);
- String16 str(jchars, len);
- env->ReleaseStringChars(jstr, jchars);
-
- //printf("the string was '%s'\n", String8(str).string());
-
- EventRecurrence er;
- if (NO_ERROR != er.parse(str)) {
- String8 msg("Error parsing recurrence: '");
- msg.append(String8(str));
- msg.append("'");
-
- jniThrowException(env,
- "android/pim/EventRecurrence$InvalidFormatException",
- msg.string());
- return ;
- }
-
- jstring untilStr;
- if (er.until.size() > 0) {
- untilStr = env->NewString(er.until.string(), er.until.size());
- if (untilStr == NULL) {
- jniThrowException(env, "java/lang/RuntimeException",
- "EventRecurrence.parse error setting field 'until'");
- return ;
- }
- } else {
- untilStr = NULL;
- }
- env->SetObjectField(This, until_field, untilStr);
-
- env->SetIntField(This, freq_field, er.freq);
- env->SetIntField(This, count_field, er.count);
- env->SetIntField(This, interval_field, er.interval);
- env->SetIntField(This, wkst_field, er.wkst);
-
- SET_ARRAY_AND_CHECK(bysecond)
- SET_ARRAY_AND_CHECK(byminute)
- SET_ARRAY_AND_CHECK(byhour)
- SET_ARRAY_AND_CHECK(byday)
- // we'll just set the bydayCount field twice, it'll be less code total
- if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)
- != NO_ERROR) {
- jniThrowException(env, "java/lang/RuntimeException",
- "EventRecurrence.parse error setting field bydayNum or "
- "bydayCount.");
- return ;
- }
- SET_ARRAY_AND_CHECK(bymonthday)
- SET_ARRAY_AND_CHECK(byyearday)
- SET_ARRAY_AND_CHECK(byweekno)
- SET_ARRAY_AND_CHECK(bymonth)
- SET_ARRAY_AND_CHECK(bysetpos)
-}
-
-/*
- * JNI registration.
- */
-static JNINativeMethod METHODS[] = {
- /* name, signature, funcPtr */
- { "parse", "(Ljava/lang/String;)V", (void*)EventRecurrence_parse }
-};
-
-static const char*const CLASS_NAME = "android/pim/EventRecurrence";
-
-int register_android_pim_EventRecurrence(JNIEnv* env)
-{
- jclass clazz = env->FindClass(CLASS_NAME);
- if (clazz == NULL) {
- LOGE("Field lookup unable to find class '%s'\n", CLASS_NAME);
- return -1;
- }
-
- freq_field = env->GetFieldID(clazz, "freq", "I");
- count_field = env->GetFieldID(clazz, "count", "I");
- interval_field = env->GetFieldID(clazz, "interval", "I");
- wkst_field = env->GetFieldID(clazz, "wkst", "I");
-
- until_field = env->GetFieldID(clazz, "until", "Ljava/lang/String;");
-
- bysecond_fields.array = env->GetFieldID(clazz, "bysecond", "[I");
- bysecond_fields.count = env->GetFieldID(clazz, "bysecondCount", "I");
- byminute_fields.array = env->GetFieldID(clazz, "byminute", "[I");
- byminute_fields.count = env->GetFieldID(clazz, "byminuteCount", "I");
- byhour_fields.array = env->GetFieldID(clazz, "byhour", "[I");
- byhour_fields.count = env->GetFieldID(clazz, "byhourCount", "I");
- byday_fields.array = env->GetFieldID(clazz, "byday", "[I");
- byday_fields.count = env->GetFieldID(clazz, "bydayCount", "I");
- bydayNum_fields.array = env->GetFieldID(clazz, "bydayNum", "[I");
- bydayNum_fields.count = byday_fields.count;
- bymonthday_fields.array = env->GetFieldID(clazz, "bymonthday", "[I");
- bymonthday_fields.count = env->GetFieldID(clazz, "bymonthdayCount", "I");
- byyearday_fields.array = env->GetFieldID(clazz, "byyearday", "[I");
- byyearday_fields.count = env->GetFieldID(clazz, "byyeardayCount", "I");
- byweekno_fields.array = env->GetFieldID(clazz, "byweekno", "[I");
- byweekno_fields.count = env->GetFieldID(clazz, "byweeknoCount", "I");
- bymonth_fields.array = env->GetFieldID(clazz, "bymonth", "[I");
- bymonth_fields.count = env->GetFieldID(clazz, "bymonthCount", "I");
- bysetpos_fields.array = env->GetFieldID(clazz, "bysetpos", "[I");
- bysetpos_fields.count = env->GetFieldID(clazz, "bysetposCount", "I");
-
- return jniRegisterNativeMethods(env, CLASS_NAME,
- METHODS, sizeof(METHODS)/sizeof(METHODS[0]));
-}
-
-}; // namespace android
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 59b97c2..fb25486 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -72,6 +72,8 @@
static jmethodID method_onInputDeviceConnectionResult;
static jmethodID method_onPanDevicePropertyChanged;
static jmethodID method_onPanDeviceConnectionResult;
+static jmethodID method_onHealthDevicePropertyChanged;
+static jmethodID method_onHealthDeviceChannelChanged;
typedef event_loop_native_data_t native_data_t;
@@ -139,6 +141,10 @@
"(Ljava/lang/String;[Ljava/lang/String;)V");
method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult",
"(Ljava/lang/String;I)V");
+ method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged",
+ "(Ljava/lang/String;[Ljava/lang/String;)V");
+ method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged",
+ "(Ljava/lang/String;Ljava/lang/String;Z)V");
method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData",
"(Ljava/lang/String;I)V");
@@ -271,6 +277,15 @@
LOG_AND_FREE_DBUS_ERROR(&err);
return JNI_FALSE;
}
+
+ dbus_bus_add_match(nat->conn,
+ "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
+ &err);
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ return JNI_FALSE;
+ }
+
dbus_bus_add_match(nat->conn,
"type='signal',interface='org.bluez.AudioSink'",
&err);
@@ -459,6 +474,12 @@
LOG_AND_FREE_DBUS_ERROR(&err);
}
dbus_bus_remove_match(nat->conn,
+ "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'",
+ &err);
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ dbus_bus_remove_match(nat->conn,
"type='signal',interface='org.bluez.audio.Manager'",
&err);
if (dbus_error_is_set(&err)) {
@@ -985,6 +1006,58 @@
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
}
goto success;
+ } else if (dbus_message_is_signal(msg,
+ "org.bluez.HealthDevice",
+ "ChannelConnected")) {
+ const char *c_path = dbus_message_get_path(msg);
+ const char *c_channel_path;
+ jboolean exists = JNI_TRUE;
+ if (dbus_message_get_args(msg, &err,
+ DBUS_TYPE_OBJECT_PATH, &c_channel_path,
+ DBUS_TYPE_INVALID)) {
+ env->CallVoidMethod(nat->me,
+ method_onHealthDeviceChannelChanged,
+ env->NewStringUTF(c_path),
+ env->NewStringUTF(c_channel_path),
+ exists);
+ } else {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
+ }
+ goto success;
+ } else if (dbus_message_is_signal(msg,
+ "org.bluez.NetworkServer",
+ "ChannelDeleted")) {
+
+ const char *c_path = dbus_message_get_path(msg);
+ const char *c_channel_path;
+ jboolean exists = JNI_FALSE;
+ if (dbus_message_get_args(msg, &err,
+ DBUS_TYPE_OBJECT_PATH, &c_channel_path,
+ DBUS_TYPE_INVALID)) {
+ env->CallVoidMethod(nat->me,
+ method_onHealthDeviceChannelChanged,
+ env->NewStringUTF(c_path),
+ env->NewStringUTF(c_channel_path),
+ exists);
+ } else {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
+ }
+ goto success;
+ } else if (dbus_message_is_signal(msg,
+ "org.bluez.HealthDevice",
+ "PropertyChanged")) {
+ jobjectArray str_array =
+ parse_health_device_property_change(env, msg);
+ if (str_array != NULL) {
+ const char *c_path = dbus_message_get_path(msg);
+ env->CallVoidMethod(nat->me,
+ method_onHealthDevicePropertyChanged,
+ env->NewStringUTF(c_path),
+ str_array);
+ } else {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
+ }
+ goto success;
}
ret = a2dp_event_filter(msg, env);
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index ac75634..036c34c 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -19,12 +19,16 @@
#define DBUS_INPUT_IFACE BLUEZ_DBUS_BASE_IFC ".Input"
#define DBUS_NETWORK_IFACE BLUEZ_DBUS_BASE_IFC ".Network"
#define DBUS_NETWORKSERVER_IFACE BLUEZ_DBUS_BASE_IFC ".NetworkServer"
-
+#define DBUS_HEALTH_MANAGER_PATH "/org/bluez"
+#define DBUS_HEALTH_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".HealthManager"
+#define DBUS_HEALTH_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".HealthDevice"
+#define DBUS_HEALTH_CHANNEL_IFACE BLUEZ_DBUS_BASE_IFC ".HealthChannel"
#define LOG_TAG "BluetoothService.cpp"
#include "android_bluetooth_common.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_util_Binder.h"
#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
@@ -1255,6 +1259,400 @@
return JNI_FALSE;
}
+static jstring registerHealthApplicationNative(JNIEnv *env, jobject object,
+ jint dataType, jstring role,
+ jstring name, jstring channelType) {
+ LOGV("%s", __FUNCTION__);
+ jstring path = NULL;
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_role = env->GetStringUTFChars(role, NULL);
+ const char *c_name = env->GetStringUTFChars(name, NULL);
+ const char *c_channel_type = env->GetStringUTFChars(channelType, NULL);
+ char *c_path;
+ DBusMessage *msg, *reply;
+ DBusError err;
+ dbus_error_init(&err);
+
+ msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
+ DBUS_HEALTH_MANAGER_PATH,
+ DBUS_HEALTH_MANAGER_IFACE,
+ "CreateApplication");
+
+ if (msg == NULL) {
+ LOGE("Could not allocate D-Bus message object!");
+ return NULL;
+ }
+
+ /* append arguments */
+ append_dict_args(msg,
+ "DataType", DBUS_TYPE_UINT16, &dataType,
+ "Role", DBUS_TYPE_STRING, &c_role,
+ "Description", DBUS_TYPE_STRING, &c_name,
+ "ChannelType", DBUS_TYPE_STRING, &c_channel_type,
+ DBUS_TYPE_INVALID);
+
+
+ /* Make the call. */
+ reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
+
+ env->ReleaseStringUTFChars(role, c_role);
+ env->ReleaseStringUTFChars(name, c_name);
+ env->ReleaseStringUTFChars(channelType, c_channel_type);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ if (!dbus_message_get_args(reply, &err,
+ DBUS_TYPE_OBJECT_PATH, &c_path,
+ DBUS_TYPE_INVALID)) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ path = env->NewStringUTF(c_path);
+ }
+ dbus_message_unref(reply);
+ }
+ }
+#endif
+ return path;
+}
+
+static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object,
+ jint dataType, jstring role,
+ jstring name) {
+ LOGV("%s", __FUNCTION__);
+ jstring path = NULL;
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_role = env->GetStringUTFChars(role, NULL);
+ const char *c_name = env->GetStringUTFChars(name, NULL);
+ char *c_path;
+
+ DBusMessage *msg, *reply;
+ DBusError err;
+ dbus_error_init(&err);
+
+ msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
+ DBUS_HEALTH_MANAGER_PATH,
+ DBUS_HEALTH_MANAGER_IFACE,
+ "CreateApplication");
+
+ if (msg == NULL) {
+ LOGE("Could not allocate D-Bus message object!");
+ return NULL;
+ }
+
+ /* append arguments */
+ append_dict_args(msg,
+ "DataType", DBUS_TYPE_UINT16, &dataType,
+ "Role", DBUS_TYPE_STRING, &c_role,
+ "Description", DBUS_TYPE_STRING, &c_name,
+ DBUS_TYPE_INVALID);
+
+
+ /* Make the call. */
+ reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err);
+
+ env->ReleaseStringUTFChars(role, c_role);
+ env->ReleaseStringUTFChars(name, c_name);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ LOGE("--_Call made getting the patch...");
+ if (!dbus_message_get_args(reply, &err,
+ DBUS_TYPE_OBJECT_PATH, &c_path,
+ DBUS_TYPE_INVALID)) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ path = env->NewStringUTF(c_path);
+ LOGE("----Path is %s", c_path);
+ }
+ dbus_message_unref(reply);
+ }
+ }
+#endif
+ return path;
+}
+
+static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object,
+ jstring path) {
+ LOGV("%s", __FUNCTION__);
+ jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ DBusError err;
+ dbus_error_init(&err);
+ DBusMessage *reply =
+ dbus_func_args_timeout(env, nat->conn, -1,
+ DBUS_HEALTH_MANAGER_PATH,
+ DBUS_HEALTH_MANAGER_IFACE, "DestroyApplication",
+ DBUS_TYPE_OBJECT_PATH, &c_path,
+ DBUS_TYPE_INVALID);
+
+ env->ReleaseStringUTFChars(path, c_path);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ result = JNI_TRUE;
+ }
+ }
+#endif
+ return result;
+}
+
+static jboolean createChannelNative(JNIEnv *env, jobject object,
+ jstring devicePath, jstring appPath, jstring config) {
+ LOGV("%s", __FUNCTION__);
+ jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+
+ if (nat) {
+ DBusError err;
+ dbus_error_init(&err);
+
+ const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
+ const char *c_app_path = env->GetStringUTFChars(appPath, NULL);
+ const char *c_config = env->GetStringUTFChars(config, NULL);
+ LOGE("Params...%s, %s, %s \n", c_device_path, c_app_path, c_config);
+
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_device_path,
+ DBUS_HEALTH_DEVICE_IFACE,
+ "CreateChannel",
+ DBUS_TYPE_OBJECT_PATH, &c_app_path,
+ DBUS_TYPE_STRING, &c_config,
+ DBUS_TYPE_INVALID);
+
+
+ env->ReleaseStringUTFChars(devicePath, c_device_path);
+ env->ReleaseStringUTFChars(appPath, c_app_path);
+ env->ReleaseStringUTFChars(config, c_config);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ result = JNI_TRUE;
+ }
+ }
+#endif
+ return result;
+}
+
+static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath,
+ jstring channelPath) {
+ LOGE("%s", __FUNCTION__);
+ jboolean result = JNI_FALSE;
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+
+ if (nat) {
+ DBusError err;
+ dbus_error_init(&err);
+
+ const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
+ const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_device_path,
+ DBUS_HEALTH_DEVICE_IFACE,
+ "DestroyChannel",
+ DBUS_TYPE_OBJECT_PATH, &c_channel_path,
+ DBUS_TYPE_INVALID);
+
+ env->ReleaseStringUTFChars(devicePath, c_device_path);
+ env->ReleaseStringUTFChars(channelPath, c_channel_path);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ result = JNI_TRUE;
+ }
+ }
+#endif
+ return result;
+}
+
+static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) {
+ LOGE("%s", __FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_device_path = env->GetStringUTFChars(devicePath, NULL);
+ DBusError err;
+ dbus_error_init(&err);
+
+ LOGE("---Args %s", c_device_path);
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_device_path,
+ DBUS_HEALTH_DEVICE_IFACE, "GetProperties",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(devicePath, c_device_path);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ DBusMessageIter iter;
+ jobjectArray str_array = NULL;
+ if (dbus_message_iter_init(reply, &iter))
+ str_array = parse_health_device_properties(env, &iter);
+ dbus_message_unref(reply);
+ jstring path = (jstring) env->GetObjectArrayElement(str_array, 1);
+
+ return path;
+ }
+ }
+#endif
+ return NULL;
+}
+
+static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring channelPath) {
+ LOGE("%s", __FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+ DBusError err;
+ dbus_error_init(&err);
+
+ LOGE("---Args %s", c_channel_path);
+
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_channel_path,
+ DBUS_HEALTH_CHANNEL_IFACE, "GetProperties",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(channelPath, c_channel_path);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ } else {
+ DBusMessageIter iter;
+ jobjectArray str_array = NULL;
+ if (dbus_message_iter_init(reply, &iter))
+ str_array = parse_health_channel_properties(env, &iter);
+ dbus_message_unref(reply);
+
+ jint len = env->GetArrayLength(str_array);
+
+ jstring name, path;
+ const char *c_name;
+
+ for (int i = 0; i < len; i+=2) {
+ name = (jstring) env->GetObjectArrayElement(str_array, i);
+ c_name = env->GetStringUTFChars(name, NULL);
+
+ if (!strcmp(c_name, "Application")) {
+ path = (jstring) env->GetObjectArrayElement(str_array, i+1);
+ LOGE("----Path is %s", env->GetStringUTFChars(path, NULL));
+ env->ReleaseStringUTFChars(name, c_name);
+ return path;
+ }
+ env->ReleaseStringUTFChars(name, c_name);
+ }
+ }
+ }
+#endif
+ return NULL;
+}
+
+static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
+ LOGV("%s", __FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_channel_path,
+ DBUS_HEALTH_CHANNEL_IFACE, "Release",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(channelPath, c_channel_path);
+
+ return reply ? JNI_TRUE : JNI_FALSE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
+static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) {
+ LOGV("%s", __FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ native_data_t *nat = get_native_data(env, object);
+ if (nat) {
+ const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL);
+ int32_t fd;
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage *reply = dbus_func_args(env, nat->conn,
+ c_channel_path,
+ DBUS_HEALTH_CHANNEL_IFACE, "Acquire",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(channelPath, c_channel_path);
+
+ if (!reply) {
+ if (dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR(&err);
+ }
+ return NULL;
+ }
+
+ fd = dbus_returns_unixfd(env, reply);
+ if (fd == -1) return NULL;
+
+ LOGE("---got fd %d\n", fd);
+ // Create FileDescriptor object
+ jobject fileDesc = jniCreateFileDescriptor(env, fd);
+ if (fileDesc == NULL) {
+ // FileDescriptor constructor has thrown an exception
+ releaseChannelFdNative(env, object, channelPath);
+ LOGE("---File Desc is null");
+ return NULL;
+ }
+
+ // Wrap it in a ParcelFileDescriptor
+ jobject parcelFileDesc = newParcelFileDescriptor(env, fileDesc);
+ if (parcelFileDesc == NULL) {
+ // ParcelFileDescriptor constructor has thrown an exception
+ releaseChannelFdNative(env, object, channelPath);
+ LOGE("---Parcel File Desc is null");
+ return NULL;
+ }
+
+ return parcelFileDesc;
+ }
+#endif
+ return NULL;
+}
+
+
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"classInitNative", "()V", (void*)classInitNative},
@@ -1317,6 +1715,24 @@
{"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
{"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
(void *)disconnectPanServerDeviceNative},
+ // Health function
+ {"registerHealthApplicationNative",
+ "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void *)registerHealthApplicationNative},
+ {"registerHealthApplicationNative",
+ "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void *)registerSinkHealthApplicationNative},
+
+ {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z",
+ (void *)unregisterHealthApplicationNative},
+ {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+ (void *)createChannelNative},
+ {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)destroyChannelNative},
+ {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative},
+ {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;",
+ (void *)getChannelApplicationNative},
+ {"getChannelFdNative", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)getChannelFdNative},
+ {"releaseChannelFdNative", "(Ljava/lang/String;)Z", (void *)releaseChannelFdNative},
};
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e301e44..537aae6 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -608,8 +608,8 @@
}
static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
- jintArray layerInfo) {
- Layer* layer = LayerRenderer::createTextureLayer();
+ jboolean isOpaque, jintArray layerInfo) {
+ Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
if (layer) {
jint* storage = env->GetIntArrayElements(layerInfo, NULL);
@@ -645,7 +645,7 @@
}
static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
- Layer* layer, jint width, jint height, jobject surface) {
+ Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
float transform[16];
sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
@@ -653,7 +653,7 @@
surfaceTexture->getTransformMatrix(transform);
GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
- LayerRenderer::updateTextureLayer(layer, width, height, renderTarget, transform);
+ LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
}
static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
@@ -795,8 +795,8 @@
{ "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
{ "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer },
{ "nResizeLayer", "(III[I)V" , (void*) android_view_GLES20Canvas_resizeLayer },
- { "nCreateTextureLayer", "([I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
- { "nUpdateTextureLayer", "(IIILandroid/graphics/SurfaceTexture;)V",
+ { "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
+ { "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
(void*) android_view_GLES20Canvas_updateTextureLayer },
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 70c2f7b..0dc9293 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -156,7 +156,7 @@
static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
{
- sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
+ sp<Surface> result(Surface_getSurface(env, clazz));
if (result == 0) {
/*
* if this method is called from the WindowManager's process, it means
@@ -189,6 +189,11 @@
return env->IsInstanceOf(obj, surfaceClass);
}
+sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) {
+ sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface));
+ return surface;
+}
+
static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
{
Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a8aff37..1a32060 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -91,6 +91,8 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
+ <protected-broadcast android:name="android.net.vpn.action.REVOKED" />
+
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
@@ -1382,7 +1384,7 @@
<permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
android:label="@string/permlab_readNetworkUsageHistory"
android:description="@string/permdesc_readNetworkUsageHistory"
- android:protectionLevel="signature" />
+ android:protectionLevel="signatureOrSystem" />
<!-- Allows an application to manage network policies (such as warning and disable
limits) and to define application-specific rules. @hide -->
@@ -1391,6 +1393,14 @@
android:description="@string/permdesc_manageNetworkPolicy"
android:protectionLevel="signature" />
+ <!-- Allows an application to account its network traffic against other UIDs. Used
+ by system services like download manager and media server. Not for use by
+ third party apps. @hide -->
+ <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
+ android:label="@string/permlab_modifyNetworkAccounting"
+ android:description="@string/permdesc_modifyNetworkAccounting"
+ android:protectionLevel="signatureOrSystem" />
+
<!-- C2DM permission.
@hide Used internally.
-->
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 1f7aeee..0000000
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
new file mode 100644
index 0000000..9409890
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
new file mode 100644
index 0000000..55acc9a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 4c1d89d..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index 6963a0e..0000000
--- a/core/res/res/drawable-hdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_holo_dark.9.png
deleted file mode 100755
index 64e2052..0000000
--- a/core/res/res/drawable-hdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index 3a84de9..0000000
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
index 6b4f66d..3cadaff 100644
--- a/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-hdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_normal.png
new file mode 100644
index 0000000..460495a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_pressed.png
new file mode 100644
index 0000000..b0f7ae9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_emergencycall_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png
new file mode 100644
index 0000000..6402d3d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png
new file mode 100644
index 0000000..83be046
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_forgotpassword_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index e21a87c..0f4bfe6 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
index 3283f99..995705d 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_ime_default.png b/core/res/res/drawable-hdpi/ic_notification_ime_default.png
new file mode 100644
index 0000000..1a9d88c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notification_ime_default.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up_holo.png
new file mode 100644
index 0000000..a686975
--- /dev/null
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_red_up_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_red_up_holo.png
new file mode 100644
index 0000000..92db8ef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_red_up_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
new file mode 100644
index 0000000..237011c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
new file mode 100644
index 0000000..2418017
--- /dev/null
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
new file mode 100644
index 0000000..2120bad
--- /dev/null
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_16.png b/core/res/res/drawable-hdpi/spinner_black_16.png
index eb34867..ef5ca35 100644
--- a/core/res/res/drawable-hdpi/spinner_black_16.png
+++ b/core/res/res/drawable-hdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_20.png b/core/res/res/drawable-hdpi/spinner_black_20.png
index dac06d7..d938931 100644
--- a/core/res/res/drawable-hdpi/spinner_black_20.png
+++ b/core/res/res/drawable-hdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_48.png b/core/res/res/drawable-hdpi/spinner_black_48.png
index 337f72a..9d1efb7 100644
--- a/core/res/res/drawable-hdpi/spinner_black_48.png
+++ b/core/res/res/drawable-hdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_black_76.png b/core/res/res/drawable-hdpi/spinner_black_76.png
index 2edc3e7..0d90881 100644
--- a/core/res/res/drawable-hdpi/spinner_black_76.png
+++ b/core/res/res/drawable-hdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_16.png b/core/res/res/drawable-hdpi/spinner_white_16.png
index 7914a68..32fa447 100644
--- a/core/res/res/drawable-hdpi/spinner_white_16.png
+++ b/core/res/res/drawable-hdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_48.png b/core/res/res/drawable-hdpi/spinner_white_48.png
index faee8ca..31fa267 100644
--- a/core/res/res/drawable-hdpi/spinner_white_48.png
+++ b/core/res/res/drawable-hdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_white_76.png b/core/res/res/drawable-hdpi/spinner_white_76.png
index cd26379..9f63292 100644
--- a/core/res/res/drawable-hdpi/spinner_white_76.png
+++ b/core/res/res/drawable-hdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default.9.png b/core/res/res/drawable-hdpi/textfield_default.9.png
old mode 100644
new mode 100755
index 4c20179..f7b6e99
--- a/core/res/res/drawable-hdpi/textfield_default.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled.9.png b/core/res/res/drawable-hdpi/textfield_disabled.9.png
old mode 100644
new mode 100755
index 81569d1..3011502
--- a/core/res/res/drawable-hdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
old mode 100644
new mode 100755
index 2591490..e0f82eb
--- a/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_selected.9.png b/core/res/res/drawable-hdpi/textfield_selected.9.png
old mode 100644
new mode 100755
index a36ed72..cf2cae3
--- a/core/res/res/drawable-hdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-hdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/title_bar_shadow.9.png b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..e6dab63
--- /dev/null
+++ b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-large-mdpi/btn_code_lock_default_holo.png
new file mode 100644
index 0000000..45cc20d
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-large-mdpi/btn_code_lock_touched_holo.png
new file mode 100644
index 0000000..45cc20d
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
new file mode 100644
index 0000000..0bc86c3
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_red_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_red_up.png
new file mode 100644
index 0000000..2ab4547
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_red_up.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_default_holo.png
new file mode 100644
index 0000000..fe72d00
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_green_holo.png
new file mode 100644
index 0000000..be666c6
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_red_holo.png
new file mode 100644
index 0000000..9627197
--- /dev/null
+++ b/core/res/res/drawable-large-mdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
deleted file mode 100644
index 48cc017..0000000
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default.png b/core/res/res/drawable-mdpi/btn_code_lock_default.png
old mode 100644
new mode 100755
index 45cc20d..f524317
--- a/core/res/res/drawable-mdpi/btn_code_lock_default.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
new file mode 100644
index 0000000..82fc3b2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched.png b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
old mode 100644
new mode 100755
index 45cc20d..5cd436c
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
new file mode 100644
index 0000000..d1fe1ad
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
deleted file mode 100755
index 66cbe48..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
deleted file mode 100644
index b6508fc..0000000
--- a/core/res/res/drawable-mdpi/btn_toggle_pressed_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_holo_dark.9.png
deleted file mode 100755
index 7daae1f..0000000
--- a/core/res/res/drawable-mdpi/cab_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
deleted file mode 100644
index cb3d0f2..0000000
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
index 97ac023..b5d3e09 100644
--- a/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_charging.png b/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
old mode 100644
new mode 100755
index 4210db2..20d6320
--- a/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_lock.png b/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
old mode 100644
new mode 100755
index 1060f5a..0206aee
--- a/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
old mode 100644
new mode 100755
index 72e4afa..bb96782
--- a/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-mdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_normal.png
new file mode 100644
index 0000000..cae795f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_pressed.png
new file mode 100644
index 0000000..2867956
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_emergencycall_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png
new file mode 100644
index 0000000..a7e063a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png
new file mode 100644
index 0000000..53af5a5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_forgotpassword_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
index c10344f..754d7bc 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
index 08c6cfe..0187a02 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_ime_default.png b/core/res/res/drawable-mdpi/ic_notification_ime_default.png
new file mode 100644
index 0000000..1a9d88c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notification_ime_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png
index 0bc86c3..7ddeba5 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up_holo.png
new file mode 100644
index 0000000..89d209c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up.png
index 2ab4547..7201e58 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up_holo.png
new file mode 100644
index 0000000..1d4cb32
--- /dev/null
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_red_up_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png
new file mode 100644
index 0000000..a627cda
--- /dev/null
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png
new file mode 100644
index 0000000..308624b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
new file mode 100644
index 0000000..6c451ec
--- /dev/null
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_16.png b/core/res/res/drawable-mdpi/spinner_black_16.png
index 5ee33ce..4b7fdfe 100644
--- a/core/res/res/drawable-mdpi/spinner_black_16.png
+++ b/core/res/res/drawable-mdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_20.png b/core/res/res/drawable-mdpi/spinner_black_20.png
index e55b60d..86d7a20 100755
--- a/core/res/res/drawable-mdpi/spinner_black_20.png
+++ b/core/res/res/drawable-mdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_48.png b/core/res/res/drawable-mdpi/spinner_black_48.png
index 3a68192..f1571f9 100644
--- a/core/res/res/drawable-mdpi/spinner_black_48.png
+++ b/core/res/res/drawable-mdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_black_76.png b/core/res/res/drawable-mdpi/spinner_black_76.png
index ec57460..e9f6e8f 100644
--- a/core/res/res/drawable-mdpi/spinner_black_76.png
+++ b/core/res/res/drawable-mdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_16.png b/core/res/res/drawable-mdpi/spinner_white_16.png
index dd2e1fd..650e315 100644
--- a/core/res/res/drawable-mdpi/spinner_white_16.png
+++ b/core/res/res/drawable-mdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_48.png b/core/res/res/drawable-mdpi/spinner_white_48.png
index d25a33e..11eacf8 100644
--- a/core/res/res/drawable-mdpi/spinner_white_48.png
+++ b/core/res/res/drawable-mdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_white_76.png b/core/res/res/drawable-mdpi/spinner_white_76.png
index f53e8ff..6c31bc3 100644
--- a/core/res/res/drawable-mdpi/spinner_white_76.png
+++ b/core/res/res/drawable-mdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default.9.png b/core/res/res/drawable-mdpi/textfield_default.9.png
index cc78e6c..1a59bb2 100644
--- a/core/res/res/drawable-mdpi/textfield_default.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled.9.png b/core/res/res/drawable-mdpi/textfield_disabled.9.png
index 9c77149..800205a 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
index 6d47708..59e1536 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_selected.9.png b/core/res/res/drawable-mdpi/textfield_selected.9.png
index 0c1b446..faadace 100644
--- a/core/res/res/drawable-mdpi/textfield_selected.9.png
+++ b/core/res/res/drawable-mdpi/textfield_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_shadow.9.png b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..dbcefee
--- /dev/null
+++ b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
new file mode 100644
index 0000000..f607251
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
new file mode 100644
index 0000000..e057cdd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png
new file mode 100644
index 0000000..2822a92
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_normal.png
new file mode 100644
index 0000000..a61f7a5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_pressed.png
new file mode 100644
index 0000000..dd5e481
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_emergencycall_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png
new file mode 100644
index 0000000..e4172ce
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png
new file mode 100644
index 0000000..e2c76217
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_forgotpassword_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
new file mode 100644
index 0000000..544924e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
new file mode 100644
index 0000000..2d28009
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png
new file mode 100644
index 0000000..d98a126
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png
new file mode 100644
index 0000000..4491f02
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png
new file mode 100644
index 0000000..6e91fbc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
new file mode 100644
index 0000000..cdc0afb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
new file mode 100644
index 0000000..36b0448
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
new file mode 100644
index 0000000..3a7a8b3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_bright.9.png b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
new file mode 100644
index 0000000..b1a8e3e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_dark.9.png b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
new file mode 100644
index 0000000..87378e1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_center_medium.9.png b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
new file mode 100644
index 0000000..ea29ed4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_bright.9.png b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
new file mode 100644
index 0000000..114faa0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_full_dark.9.png b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
new file mode 100644
index 0000000..996beaa
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_bright.9.png b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
new file mode 100644
index 0000000..64e4139
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_top_dark.9.png b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
new file mode 100644
index 0000000..902bc29
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_16.png b/core/res/res/drawable-xhdpi/spinner_black_16.png
new file mode 100644
index 0000000..5b1422c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_20.png b/core/res/res/drawable-xhdpi/spinner_black_20.png
new file mode 100644
index 0000000..5f53e38
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_20.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_48.png b/core/res/res/drawable-xhdpi/spinner_black_48.png
new file mode 100644
index 0000000..3aab620
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_black_76.png b/core/res/res/drawable-xhdpi/spinner_black_76.png
new file mode 100644
index 0000000..2968d8c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_black_76.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_16.png b/core/res/res/drawable-xhdpi/spinner_white_16.png
new file mode 100644
index 0000000..69be752
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_16.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_48.png b/core/res/res/drawable-xhdpi/spinner_white_48.png
new file mode 100644
index 0000000..7b196bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_48.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_white_76.png b/core/res/res/drawable-xhdpi/spinner_white_76.png
new file mode 100644
index 0000000..ba47005
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_white_76.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_alarm.png
new file mode 100644
index 0000000..29cd471
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_charging.png b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_charging.png
new file mode 100644
index 0000000..211aa0b
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_lock.png b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_lock.png
new file mode 100644
index 0000000..683ba22
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_low_battery.png
new file mode 100644
index 0000000..f4383f3
--- /dev/null
+++ b/core/res/res/drawable-xlarge-hdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png
new file mode 100644
index 0000000..97ac023
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png
new file mode 100644
index 0000000..4210db2
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png
new file mode 100644
index 0000000..1060f5a
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png
new file mode 100644
index 0000000..72e4afa
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png
new file mode 100644
index 0000000..9f7a132
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_default.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png
new file mode 100644
index 0000000..9f7a132
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_default.png
new file mode 100644
index 0000000..6662eb1
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_default.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_green.png
new file mode 100644
index 0000000..dce220a
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_green.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_red.png b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_red.png
new file mode 100644
index 0000000..746a3ea
--- /dev/null
+++ b/core/res/res/drawable-xlarge-xhdpi/indicator_code_lock_point_area_red.png
Binary files differ
diff --git a/core/res/res/drawable/lockscreen_emergency_button.xml b/core/res/res/drawable/lockscreen_emergency_button.xml
new file mode 100644
index 0000000..4ec6a96
--- /dev/null
+++ b/core/res/res/drawable/lockscreen_emergency_button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="true" android:drawable="@drawable/ic_lockscreen_emergencycall_normal" />
+ <item android:state_pressed="true" android:drawable="@drawable/ic_lockscreen_emergencycall_pressed" />
+ <item android:drawable="@drawable/ic_lockscreen_emergencycall_normal" />
+</selector>
diff --git a/core/res/res/drawable/lockscreen_forgot_password_button.xml b/core/res/res/drawable/lockscreen_forgot_password_button.xml
new file mode 100644
index 0000000..6c081bf
--- /dev/null
+++ b/core/res/res/drawable/lockscreen_forgot_password_button.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="true" android:drawable="@drawable/ic_lockscreen_forgotpassword_normal" />
+ <item android:state_pressed="true" android:drawable="@drawable/ic_lockscreen_forgotpassword_pressed" />
+ <item android:drawable="@drawable/ic_lockscreen_forgotpassword_normal" />
+</selector>
diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml
new file mode 100644
index 0000000..c3e6deb
--- /dev/null
+++ b/core/res/res/layout-land/ssl_certificate.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:id="@+id/body"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <!-- Placeholder for the success message or one or more warnings -->
+ <LinearLayout
+ android:id="@+id/placeholder"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dip"
+ android:orientation="vertical" />
+
+ <!-- Dialog-title line separator -->
+ <ImageView
+ android:id="@+id/title_separator"
+ android:src="@android:drawable/divider_horizontal_dark"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_weight="1"
+ android:gravity="fill_horizontal"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:shrinkColumns="1"
+ android:orientation="vertical">
+
+ <!-- Issued to: -->
+ <TextView
+ android:id="@+id/issued_to_header"
+ android:text="@string/issued_to"
+ android:textStyle="bold"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+
+ <!-- Common name: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/to_common_header"
+ android:text="@string/common_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/to_common"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+ </TableRow>
+
+ <!-- Organization: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/to_org_header"
+ android:text="@string/org_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/to_org"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+ </TableRow>
+
+ <!-- Organizational unit: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/to_org_unit_header"
+ android:text="@string/org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/to_org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+ </TableRow>
+
+ <!-- Issued by: -->
+ <TextView
+ android:id="@+id/issued_to_header"
+ android:text="@string/issued_by"
+ android:textStyle="bold"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+
+ <!-- Common name: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/by_common_header"
+ android:text="@string/common_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/by_common"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+ </TableRow>
+
+ <!-- Organization: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/by_org_header"
+ android:text="@string/org_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/by_org"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+ </TableRow>
+
+ <!-- Organizational unit: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/by_org_unit_header"
+ android:text="@string/org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/by_org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+ </TableRow>
+
+ <!-- Validity Dates: -->
+ <TextView
+ android:id="@+id/validity_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/validity_period"
+ android:textStyle="bold"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+
+ <!-- Issued On: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/issued_on_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/issued_on"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/issued_on"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="7dip" />
+
+ </TableRow>
+
+ <!-- Expires On: -->
+ <TableRow>
+ <TextView
+ android:id="@+id/expires_on_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/expires_on"
+ android:gravity="left"
+ android:layout_marginLeft="20dip" />
+
+ <TextView
+ android:id="@+id/expires_on"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+ </TableRow>
+
+ </TableLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/layout-large/action_bar_home.xml b/core/res/res/layout-large/action_bar_home.xml
deleted file mode 100644
index 86580bc..0000000
--- a/core/res/res/layout-large/action_bar_home.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<view xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.internal.widget.ActionBarView$HomeView"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground" >
- <ImageView android:id="@android:id/up"
- android:src="?android:attr/homeAsUpIndicator"
- android:layout_gravity="center_vertical|left"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="-12dip" />
- <ImageView android:id="@android:id/home"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="16dip"
- android:paddingRight="16dip"
- android:paddingTop="4dip"
- android:paddingBottom="4dip"
- android:adjustViewBounds="true"
- android:layout_gravity="center"
- android:scaleType="fitCenter" />
-</view>
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
new file mode 100644
index 0000000..004d52a
--- /dev/null
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/datePicker"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
index 9779074..56c832c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_glogin_unlock.xml
@@ -26,7 +26,7 @@
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
- android:layout_above="@+id/emergencyCall">
+ android:layout_above="@+id/emergencyCallButton">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -123,7 +123,7 @@
<!-- emergency call button at bottom center -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index 1783088..6579e76 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -95,7 +95,7 @@
<!-- emergency call button NOT CURRENTLY USED -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_emergency"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 63241dd..c63b0ff 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -87,7 +87,7 @@
<!-- emergency call button -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_emergency"
@@ -98,4 +98,4 @@
/>
</LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
index b8cbe51..c65dd83 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_landscape.xml
@@ -104,7 +104,7 @@
android:textSize="18sp"
/>
- <Button android:id="@+id/emergencyCall"
+ <Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
index 009148f..d8bea56 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_sim_pin_portrait.xml
@@ -93,7 +93,7 @@
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginTop="6dip"
- android:layout_above="@id/emergencyCall"
+ android:layout_above="@id/emergencyCallButton"
android:background="@android:drawable/divider_horizontal_dark"
/>
@@ -107,7 +107,7 @@
<!-- emergency call button -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_emergency"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
index 0a485e2..302ee01 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -56,7 +56,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="98sp"
+ android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_background"
android:layout_marginBottom="6dip"
@@ -67,7 +67,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="98sp"
+ android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_foreground"
android:layout_alignLeft="@id/timeDisplayBackground"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
index 346b21e..53fe902 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -55,7 +55,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="98sp"
+ android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_background"
android:layout_marginBottom="6dip"
@@ -66,7 +66,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="98sp"
+ android:textSize="@dimen/keyguard_pattern_unlock_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_foreground"
android:layout_marginBottom="6dip"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
index e3d7a3f..7ac41b5 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_landscape.xml
@@ -56,10 +56,8 @@
android:layout_gravity="center_vertical"
/>
- <!-- footer -->
-
- <!-- option 1: a single emergency call button -->
- <RelativeLayout android:id="@+id/footerNormal"
+ <!-- Emergency and forgot pattern buttons. -->
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/lockPattern"
@@ -68,43 +66,27 @@
android:layout_marginTop="28dip"
android:layout_marginLeft="28dip"
android:layout_marginRight="28dip"
- >
- <Button android:id="@+id/emergencyCallAlone"
+ android:orientation="horizontal">
+
+ <Button android:id="@+id/forgotPatternButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
+ android:layout_gravity="center"
style="@style/Widget.Button.Transparent"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="8dip"
+ android:text="@string/lockscreen_forgot_pattern_button_text"
android:visibility="gone"
- />
- </RelativeLayout>
-
- <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
- <LinearLayout android:id="@+id/footerForgotPattern"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/footerNormal"
- android:layout_alignLeft="@id/lockPattern"
- android:layout_alignRight="@id/lockPattern"
- android:layout_marginTop="28dip"
- android:layout_marginLeft="28dip"
- android:layout_marginRight="28dip">
-
- <Button android:id="@+id/forgotPattern"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/Widget.Button.Transparent"
/>
- <Button android:id="@+id/emergencyCallTogether"
- android:layout_width="match_parent"
+ <Button android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
+ android:layout_gravity="center"
style="@style/Widget.Button.Transparent"
android:drawableLeft="@drawable/ic_emergency"
android:drawablePadding="8dip"
+ android:text="@string/lockscreen_emergency_call"
android:visibility="gone"
/>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
index f35897e..1f6058f 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_unlock_portrait.xml
@@ -23,7 +23,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <!-- top: status -->
+ <!-- top: status and emergency/forgot pattern buttons -->
<LinearLayout
android:layout_height="0dip"
android:layout_weight="1"
@@ -36,53 +36,37 @@
android:layout_marginTop="134dip"
android:layout_marginLeft="266dip"/>
- <!-- footer -->
- <FrameLayout
+ <!-- Emergency and forgot pattern buttons. -->
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="140dip"
- >
+ android:orientation="horizontal"
+ android:gravity="center_horizontal">
- <!-- option 1: a single emergency call button -->
- <RelativeLayout android:id="@+id/footerNormal"
- android:layout_width="match_parent"
+ <Button android:id="@+id/forgotPatternButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="left"
- >
- <Button android:id="@+id/emergencyCallAlone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- android:visibility="gone"
- />
- </RelativeLayout>
+ android:layout_gravity="center"
+ style="@style/Widget.Button.Transparent"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ android:text="@string/lockscreen_forgot_pattern_button_text"
+ android:visibility="gone"
+ />
- <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
- <LinearLayout android:id="@+id/footerForgotPattern"
- android:orientation="vertical"
- android:layout_width="match_parent"
+ <Button android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="left"
- >
- <Button android:id="@+id/forgotPattern"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/Widget.Button.Transparent"
- />
- <Button android:id="@+id/emergencyCallTogether"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- android:visibility="gone"
- />
- </LinearLayout>
- </FrameLayout>
+ android:layout_gravity="center"
+ style="@style/Widget.Button.Transparent"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ android:text="@string/lockscreen_emergency_call"
+ android:visibility="gone"
+ />
+
+ </LinearLayout>
+
</LinearLayout>
<!-- right side: lock pattern -->
diff --git a/core/res/res/layout-sw600dp/number_picker.xml b/core/res/res/layout-sw600dp/number_picker.xml
new file mode 100644
index 0000000..807daf2
--- /dev/null
+++ b/core/res/res/layout-sw600dp/number_picker.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageButton android:id="@+id/increment"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/numberPickerUpButtonStyle"
+ android:contentDescription="@string/number_picker_increment_button" />
+
+ <EditText android:id="@+id/numberpicker_input"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/numberPickerInputTextStyle" />
+
+ <ImageButton android:id="@+id/decrement"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ style="?android:attr/numberPickerDownButtonStyle"
+ android:contentDescription="@string/number_picker_decrement_button" />
+
+</merge>
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index 7f7c55c..9612710 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -25,14 +25,13 @@
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="-4dip" />
+ android:layout_marginRight="-8dip" />
<ImageView android:id="@android:id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingTop="@dimen/action_bar_icon_vertical_padding"
- android:paddingBottom="@dimen/action_bar_icon_vertical_padding"
+ android:layout_marginRight="8dip"
+ android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
+ android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index d8b729d..e803b26 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -17,17 +17,32 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingRight="32dip" >
- <TextView android:id="@+id/action_bar_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end" />
- <TextView android:id="@+id/action_bar_subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone" />
+ android:orientation="horizontal"
+ android:paddingRight="16dip"
+ android:background="?android:attr/selectableItemBackground"
+ android:enabled="false">
+
+ <ImageView android:id="@android:id/up"
+ android:src="?android:attr/homeAsUpIndicator"
+ android:layout_gravity="center_vertical|left"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|left"
+ android:orientation="vertical">
+ <TextView android:id="@+id/action_bar_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end" />
+ <TextView android:id="@+id/action_bar_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone" />
+ </LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index 4206dcb..a8f0c22 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -29,10 +29,10 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
- android:paddingTop="@dimen/action_bar_icon_vertical_padding"
- android:paddingBottom="@dimen/action_bar_icon_vertical_padding"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_marginBottom="4dip"
+ android:layout_marginLeft="4dip"
+ android:layout_marginRight="4dip"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:background="@null"
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 1a3573e..2185467 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -82,7 +82,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dip"
- android:paddingRight="16dip" />
+ android:paddingRight="16dip"
+ android:paddingTop="8dip"
+ android:paddingBottom="8dip"/>
</ScrollView>
</LinearLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 004d52a..db8f311 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -22,4 +22,6 @@
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:spinnersShown="true"
+ android:calendarViewShown="false"
/>
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index 026cbfb..8627637 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -77,7 +77,8 @@
android:id="@+id/calendar_view"
android:layout_width="245dip"
android:layout_height="280dip"
- android:layout_marginLeft="22dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:layout_weight="1"
android:focusable="true"
android:focusableInTouchMode="true"
diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
index 8a46546..0e5fe78 100644
--- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml
@@ -26,7 +26,7 @@
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
- android:layout_above="@+id/emergencyCall">
+ android:layout_above="@+id/emergencyCallButton">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -114,7 +114,7 @@
<!-- emergency call button at bottom center -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index aac0853..8ba08f6 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
-** Copyright 2008, The Android Open Source Project
+** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License")
** you may not use this file except in compliance with the License.
@@ -17,89 +17,180 @@
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- This is the general lock screen which shows information about the
+ state of the device, as well as instructions on how to get past it
+ depending on the state of the device.-->
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:rowCount="11"
+ android:id="@+id/root"
+ android:clipChildren="false">
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- />
+ <!-- Column 0 -->
+ <Space android:height="20dip"/>
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="8dip"
+ android:layout_gravity="right">
- <!-- left side: status -->
- <include layout="@layout/keyguard_screen_status_land"
+ <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+ top of the other. Hence the redundant layout... -->
+ <TextView android:id="@+id/timeDisplayBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_alignParentLeft="true"/>
-
- <!-- right side: password -->
- <LinearLayout
- android:layout_width="300dip"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true">
-
- <!-- Password entry field -->
- <EditText android:id="@+id/passwordEntry"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:singleLine="true"
- android:textStyle="normal"
- android:inputType="textPassword"
- android:gravity="center"
- android:textSize="24sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:background="@drawable/lockscreen_password_field_dark"
- android:textColor="#ffffffff"
- />
-
- <!-- Numeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
- android:layout_width="300dip"
- android:layout_height="400dip"
- android:background="#40000000"
- android:layout_marginTop="5dip"
- android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- android:visibility="gone"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_background"
/>
- </LinearLayout>
- </RelativeLayout>
+ <TextView android:id="@+id/timeDisplayForeground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_foreground"
+ android:layout_alignLeft="@id/timeDisplayBackground"
+ android:layout_alignTop="@id/timeDisplayBackground"
+ />
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
+ </com.android.internal.widget.DigitalClock>
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_below="@id/time"
+ android:layout_marginTop="6dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/alarm_status"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_marginTop="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_marginTop="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/screenLocked"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:gravity="center"
+ android:layout_marginTop="4dip"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <Space android:height="20dip"/>
+
+ <TextView
+ android:id="@+id/carrier"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:layout_gravity="right"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
/>
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/password_keyboard_background_holo"
- android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- android:keyTextSize="18dip"
- android:visibility="gone"
+ <!-- "emergency calls only" shown when sim is missing or PUKd -->
+ <TextView
+ android:id="@+id/emergencyCallText"
+ android:layout_marginTop="20dip"
+ android:layout_gravity="right"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:text="@string/emergency_calls_only"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
/>
- <!-- emergency call button NOT CURRENTLY USED -->
<Button
- android:id="@+id/emergencyCall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
+ android:id="@+id/emergencyCallButton"
+ android:layout_gravity="right"
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
android:text="@string/lockscreen_emergency_call"
- android:visibility="gone"
- style="@style/Widget.Button.Transparent"
+ style="?android:attr/buttonBarButtonStyle"
+ android:drawablePadding="8dip"
+ android:visibility="visible"
/>
-</LinearLayout>
+ <!-- Column 1 -->
+ <Space android:layout_columnWeight="1" android:layout_rowSpan="11" />
+
+ <!-- Column 2 - password entry field and PIN keyboard -->
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center|fill"
+ android:layout_rowSpan="11">
+
+ <EditText android:id="@+id/passwordEntry"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:singleLine="true"
+ android:textStyle="normal"
+ android:inputType="textPassword"
+ android:layout_gravity="center"
+ android:textSize="24sp"
+ android:minEms="8"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:background="@drawable/lockscreen_password_field_dark"
+ android:textColor="?android:attr/textColorPrimary"
+ />
+
+ <!-- Numeric keyboard -->
+ <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
+ android:layout_width="250dip"
+ android:layout_height="100dip"
+ android:layout_gravity="center"
+ android:background="#40000000"
+ android:layout_marginTop="5dip"
+ android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+ android:visibility="visible"
+ />
+
+ </LinearLayout>
+
+</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 7805672b..6953ac8 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -24,24 +24,27 @@
<!-- top: status -->
<RelativeLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:layout_marginRight="16dip">
<include layout="@layout/keyguard_screen_status_port"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"/>
+ android:layout_alignParentRight="true"/>
</RelativeLayout>
<!-- emergency call button -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:drawableLeft="@drawable/ic_emergency"
+ android:layout_marginTop="4dip"
+ android:layout_marginRight="16dip"
+ android:layout_gravity="right"
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
android:drawablePadding="8dip"
android:text="@string/lockscreen_emergency_call"
- android:visibility="gone"
- style="@style/Widget.Button.Transparent"
+ style="?android:attr/buttonBarButtonStyle"
/>
<!-- bottom: password -->
@@ -55,6 +58,8 @@
android:inputType="textPassword"
android:gravity="center"
android:textSize="22sp"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
android:background="@drawable/lockscreen_password_field_dark"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffffffff"/>
@@ -83,4 +88,17 @@
android:visibility="gone"
/>
-</LinearLayout>
\ No newline at end of file
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="8dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ />
+
+</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
index 244afbe..dff2a3f 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_landscape.xml
@@ -102,7 +102,7 @@
android:textSize="18sp"
/>
- <Button android:id="@+id/emergencyCall"
+ <Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
diff --git a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
index 009148f..d8bea56 100644
--- a/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_pin_portrait.xml
@@ -93,7 +93,7 @@
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginTop="6dip"
- android:layout_above="@id/emergencyCall"
+ android:layout_above="@id/emergencyCallButton"
android:background="@android:drawable/divider_horizontal_dark"
/>
@@ -107,7 +107,7 @@
<!-- emergency call button -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_emergency"
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
index d58fb23..11a6e12 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_landscape.xml
@@ -164,7 +164,7 @@
android:textSize="18sp"
/>
- <Button android:id="@+id/emergencyCall"
+ <Button android:id="@+id/emergencyCallButton"
android:text="@android:string/lockscreen_emergency_call"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
diff --git a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
index 5e392ef..e5e0459 100644
--- a/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_sim_puk_portrait.xml
@@ -159,7 +159,7 @@
android:layout_width="match_parent"
android:layout_height="1dip"
android:layout_marginTop="6dip"
- android:layout_above="@id/emergencyCall"
+ android:layout_above="@id/emergencyCallButton"
android:background="@android:drawable/divider_horizontal_dark"
/>
@@ -173,7 +173,7 @@
<!-- emergency call button -->
<Button
- android:id="@+id/emergencyCall"
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_emergency"
diff --git a/core/res/res/layout/keyguard_screen_status_land.xml b/core/res/res/layout/keyguard_screen_status_land.xml
index 259a3af..021faa3 100644
--- a/core/res/res/layout/keyguard_screen_status_land.xml
+++ b/core/res/res/layout/keyguard_screen_status_land.xml
@@ -26,17 +26,6 @@
android:gravity="left"
>
- <TextView
- android:id="@+id/carrier"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:drawablePadding="4dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- />
-
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -52,7 +41,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="40sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_background"
android:layout_marginBottom="6dip"
@@ -63,7 +52,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="40sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_foreground"
android:layout_alignLeft="@id/timeDisplayBackground"
@@ -71,19 +60,6 @@
android:layout_marginBottom="6dip"
/>
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="18sp"
- android:layout_marginLeft="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
</com.android.internal.widget.DigitalClock>
<LinearLayout
@@ -97,16 +73,20 @@
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"/>
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
<TextView
android:id="@+id/alarm_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"/>
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
</LinearLayout>
@@ -116,8 +96,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:layout_marginTop="10dip"
android:drawablePadding="4dip"
android:visibility="gone"
@@ -129,20 +111,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
- android:textSize="17sp"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
- <TextView
- android:id="@+id/propertyOf"
- android:lineSpacingExtra="8dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:layout_marginTop="20dip"
- android:singleLine="false"
- android:textColor="@color/lockscreen_owner_info"
- android:visibility="gone"
- />
</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_status_port.xml b/core/res/res/layout/keyguard_screen_status_port.xml
index 680c073..f84e61c2 100644
--- a/core/res/res/layout/keyguard_screen_status_port.xml
+++ b/core/res/res/layout/keyguard_screen_status_port.xml
@@ -25,23 +25,10 @@
android:layout_height="wrap_content"
android:gravity="left">
- <TextView
- android:id="@+id/carrier"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:drawablePadding="4dip"
- android:layout_marginTop="10dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- />
-
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip">
+ android:layout_marginTop="8dip">
<!-- Because we can't have multi-tone fonts, we render two TextViews, one on
top of the other. Hence the redundant layout... -->
@@ -50,7 +37,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="60sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_background"
android:layout_marginBottom="6dip"
@@ -61,7 +48,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="60sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/lockscreen_clock_foreground"
android:layout_marginBottom="6dip"
@@ -69,19 +56,6 @@
android:layout_alignTop="@id/timeDisplayBackground"
/>
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="22sp"
- android:layout_marginLeft="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
</com.android.internal.widget.DigitalClock>
<LinearLayout
@@ -89,57 +63,58 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/time"
- android:layout_marginTop="10dip">
+ android:layout_marginTop="16dip"
+ android:layout_gravity="right">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"/>
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
<TextView
android:id="@+id/alarm_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="30dip"
+ android:layout_marginLeft="16dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"/>
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"/>
</LinearLayout>
- <!-- used for status such as the next alarm, and charging status. -->
- <TextView
- android:id="@+id/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:layout_marginTop="10dip"
- android:drawablePadding="4dip"
- android:visibility="gone"
- />
-
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="10dip"
- android:textSize="17sp"
+ android:layout_gravity="right"
+ android:layout_marginTop="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
/>
+ <!-- used for status such as the next alarm, and charging status. -->
<TextView
- android:id="@+id/propertyOf"
- android:lineSpacingExtra="8dip"
+ android:id="@+id/status2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="20dip"
+ android:layout_gravity="right"
+ android:layout_alignParentTop="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:singleLine="false"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_marginTop="4dip"
+ android:drawablePadding="4dip"
android:visibility="gone"
- android:textColor="@color/lockscreen_owner_info"
/>
+
+
</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 7ae357a..1e2abf9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -28,43 +28,14 @@
android:id="@+id/root"
android:clipChildren="false">
- <TextView
- android:id="@+id/carrier"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_marginTop="10dip"
- android:layout_marginRight="8dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="right|bottom"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
-
- <!-- "emergency calls only" shown when sim is missing or PUKd -->
- <TextView
- android:id="@+id/emergencyCallText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/carrier"
- android:layout_alignParentRight="true"
- android:layout_marginTop="0dip"
- android:layout_marginRight="8dip"
- android:text="@string/emergency_calls_only"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/white"
- />
-
<!-- time and date -->
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/carrier"
- android:layout_marginTop="52dip"
- android:layout_marginLeft="20dip"
- android:layout_marginBottom="8dip"
- >
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="16dip"
+ android:layout_marginTop="48dip"
+ android:layout_marginLeft="20dip">
<!-- Because we can't have multi-tone fonts, we render two TextViews, one on
top of the other. Hence the redundant layout... -->
@@ -73,7 +44,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="72sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginBottom="6dip"
android:textColor="@color/lockscreen_clock_background"
@@ -84,7 +55,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="none"
- android:textSize="72sp"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginBottom="6dip"
android:textColor="@color/lockscreen_clock_foreground"
@@ -92,51 +63,56 @@
android:layout_alignTop="@id/timeDisplayBackground"
/>
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="22sp"
- android:layout_marginLeft="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
</com.android.internal.widget.DigitalClock>
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
+ <LinearLayout android:id="@+id/date_alarm_status_container"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/time"
- android:layout_marginLeft="24dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_marginTop="16dip"
+ android:layout_alignParentRight="true"
+ android:gravity="right"
+ android:orientation="horizontal">
- <!-- TODO: Redo layout when we release on phones -->
- <TextView
- android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- android:drawablePadding="4dip"
- android:layout_below="@id/date"
- android:layout_marginTop="4dip"
- android:layout_marginLeft="24dip"
- />
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ />
+
+ <TextView
+ android:id="@+id/alarm_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_marginLeft="16dip"
+ />
+
+ </LinearLayout>
<TextView
android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/alarm_status"
+ android:layout_below="@id/date_alarm_status_container"
android:layout_marginTop="4dip"
- android:layout_marginLeft="24dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_alignParentRight="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
/>
@@ -146,9 +122,15 @@
android:layout_height="wrap_content"
android:layout_below="@id/status1"
android:layout_marginTop="4dip"
- android:layout_marginLeft="24dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_alignParentRight="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
+ android:visibility="gone"
/>
<TextView
@@ -156,46 +138,92 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/status2"
- android:layout_marginLeft="24dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_alignParentRight="true"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:layout_marginTop="12dip"
android:drawablePadding="4dip"
+ android:visibility="gone"
/>
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/unlock_widget"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="300dip"
- android:layout_alignParentBottom="true"
-
- android:targetDrawables="@array/lockscreen_targets_when_silent"
- android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@*android:dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
- android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
- android:vibrationDuration="20"
- android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
- android:feedbackCount="3"
- android:horizontalOffset="0dip"
- android:verticalOffset="60dip"
- />
-
- <!-- emergency call button shown when sim is PUKd and tab_selector is
- hidden -->
+ <!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
<Button
android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:drawableLeft="@drawable/ic_emergency"
- android:layout_centerInParent="true"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="80dip"
- style="@style/Widget.Button.Transparent"
- android:drawablePadding="8dip"
- android:visibility="gone"
+ android:layout_marginTop="4dip"
+ android:layout_marginRight="16dip"
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
+ android:layout_alignParentRight="true"
+ android:layout_below="@id/screenLocked"
+ style="?android:attr/buttonBarButtonStyle"
+ android:drawablePadding="4dip"
+ android:text="@string/lockscreen_emergency_call"
+ android:visibility="visible"
/>
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:gravity="center_horizontal">
+
+ <com.android.internal.widget.multiwaveview.MultiWaveView
+ android:id="@+id/unlock_widget"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="300dip"
+ android:layout_alignParentBottom="true"
+
+ android:targetDrawables="@array/lockscreen_targets_when_silent"
+ android:handleDrawable="@drawable/ic_lockscreen_handle"
+ android:waveDrawable="@drawable/ic_lockscreen_outerring"
+ android:outerRadius="@dimen/multiwaveview_target_placement_radius"
+ android:snapMargin="@dimen/multiwaveview_snap_margin"
+ android:hitRadius="@dimen/multiwaveview_hit_radius"
+ android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
+ android:horizontalOffset="0dip"
+ android:verticalOffset="60dip"
+ android:feedbackCount="3"
+ android:vibrationDuration="20"
+ />
+
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="8dip"
+ android:gravity="center_horizontal"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <!-- "emergency calls only" shown when sim is missing or PUKd -->
+ <TextView
+ android:id="@+id/emergencyCallText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_above="@id/carrier"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="0dip"
+ android:layout_marginRight="8dip"
+ android:text="@string/emergency_calls_only"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ </RelativeLayout>
+
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index df29a4b..5588adc 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -20,32 +20,124 @@
<!-- This is the general lock screen which shows information about the
state of the device, as well as instructions on how to get past it
depending on the state of the device.-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal"
+ android:orientation="vertical"
+ android:rowCount="10"
android:id="@+id/root"
android:clipChildren="false">
- <!-- left side -->
- <RelativeLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:layout_marginLeft="24dip"
- android:gravity="left">
+ <!-- Column 0 -->
+ <Space android:height="20dip"/>
- <TextView
+ <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="8dip"
+ android:layout_gravity="right">
+
+ <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+ top of the other. Hence the redundant layout... -->
+ <TextView android:id="@+id/timeDisplayBackground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_background"
+ />
+
+ <TextView android:id="@+id/timeDisplayForeground"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_foreground"
+ android:layout_alignLeft="@id/timeDisplayBackground"
+ android:layout_alignTop="@id/timeDisplayBackground"
+ />
+
+ </com.android.internal.widget.DigitalClock>
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_below="@id/time"
+ android:layout_marginTop="6dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/alarm_status"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_marginTop="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_marginTop="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_marginTop="4dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <TextView
+ android:id="@+id/screenLocked"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:gravity="center"
+ android:layout_marginTop="4dip"
+ android:drawablePadding="4dip"
+ android:layout_gravity="right"
+ />
+
+ <Space android:height="20dip"/>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_gravity="right"
+ android:gravity="fill_horizontal">
+
+ <TextView
android:id="@+id/carrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- android:layout_marginTop="20dip"
android:singleLine="true"
android:ellipsize="marquee"
- android:gravity="right|bottom"
+ android:layout_gravity="right"
android:textAppearance="?android:attr/textAppearanceMedium"
- />
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
+ />
<!-- "emergency calls only" shown when sim is missing or PUKd -->
<TextView
@@ -54,145 +146,49 @@
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="20dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:text="@string/emergency_calls_only"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/white"
- />
-
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/carrier"
- android:layout_marginTop="56dip"
- android:layout_marginBottom="8dip"
- >
-
- <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
- top of the other. Hence the redundant layout... -->
- <TextView android:id="@+id/timeDisplayBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="72sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_background"
- />
-
- <TextView android:id="@+id/timeDisplayForeground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="72sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_foreground"
- android:layout_alignLeft="@id/timeDisplayBackground"
- android:layout_alignTop="@id/timeDisplayBackground"
- />
-
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="22sp"
- android:layout_marginLeft="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
- </com.android.internal.widget.DigitalClock>
-
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/time"
- android:layout_marginTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
- />
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
+ android:layout_gravity="right"
+ />
- <!-- TODO: Redo layout when we release on phones -->
- <TextView
- android:id="@+id/alarm_status"
+ <Button
+ android:id="@+id/emergencyCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- android:drawablePadding="4dip"
- android:layout_below="@id/date"
- android:layout_marginTop="4dip"
- android:layout_marginLeft="24dip"
- />
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
+ android:text="@string/lockscreen_emergency_call"
+ style="?android:attr/buttonBarButtonStyle"
+ android:drawablePadding="8dip"
+ android:visibility="visible"
+ android:layout_gravity="right"
+ />
+ </LinearLayout>
- <TextView
- android:id="@+id/status1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/alarm_status"
- android:layout_marginTop="6dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:drawablePadding="4dip"
- />
+ <!-- Column 1 -->
+ <Space android:width="20dip" android:layout_columnWeight="1" android:layout_rowSpan="10" />
- <TextView
- android:id="@+id/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/status1"
- android:layout_marginTop="6dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:drawablePadding="4dip"
- />
-
- <TextView
- android:id="@+id/screenLocked"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/status2"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="center"
- android:layout_marginTop="12dip"
- android:drawablePadding="4dip"
- />
-
- </RelativeLayout>
-
- <!-- right side -->
+ <!-- Column 2 -->
<com.android.internal.widget.multiwaveview.MultiWaveView
android:id="@+id/unlock_widget"
android:layout_width="300dip"
android:layout_height="match_parent"
+ android:layout_rowSpan="10"
android:targetDrawables="@array/lockscreen_targets_when_silent"
android:handleDrawable="@drawable/ic_lockscreen_handle"
android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@*android:dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
- android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
- android:vibrationDuration="20"
+ android:outerRadius="@dimen/multiwaveview_target_placement_radius"
+ android:snapMargin="@dimen/multiwaveview_snap_margin"
+ android:hitRadius="@dimen/multiwaveview_hit_radius"
android:topChevronDrawable="@drawable/ic_lockscreen_chevron_up"
android:feedbackCount="3"
- android:horizontalOffset="60dip"
+ android:vibrationDuration="20"
+ android:horizontalOffset="0dip"
android:verticalOffset="0dip"
/>
- <!-- emergency call button shown when sim is PUKd and tab_selector is
- hidden -->
- <Button
- android:id="@+id/emergencyCallButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableLeft="@drawable/ic_emergency"
- style="@style/Widget.Button.Transparent"
- android:drawablePadding="8dip"
- android:layout_marginRight="80dip"
- android:visibility="gone"
- />
-
-</LinearLayout>
+</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index c7b78c4..d0538dd 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -21,198 +21,137 @@
the user how to unlock their device, or make an emergency call. This
is the portrait layout. -->
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
+<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/root"
+ android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:rowCount="7">
- <!-- left side: instructions and emergency call button -->
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:layout_marginLeft="24dip"
- android:gravity="left"
- >
+ <!-- Column 0: Time, date and status -->
+ <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:layout_marginBottom="12dip"
+ android:layout_gravity="right">
- <TextView
- android:id="@+id/alarm_status"
+ <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+ top of the other. Hence the redundant layout... -->
+ <TextView android:id="@+id/timeDisplayBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- android:drawablePadding="4dip"
- />
- <TextView
- android:id="@+id/status1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
-
- <TextView
- android:id="@+id/carrier"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:drawablePadding="4dip"
- android:layout_marginTop="32dip"
android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="right|bottom"
- />
-
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- >
-
- <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
- top of the other. Hence the redundant layout... -->
- <TextView android:id="@+id/timeDisplayBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="72sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_background"
- />
-
- <TextView android:id="@+id/timeDisplayForeground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="72sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:layout_alignLeft="@id/timeDisplayBackground"
- android:layout_alignTop="@id/timeDisplayBackground"
- android:textColor="@color/lockscreen_clock_foreground"
- />
-
-
-
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="22sp"
- android:layout_marginLeft="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
- </com.android.internal.widget.DigitalClock>
-
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/time"
+ android:ellipsize="none"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_background"
/>
- <!-- used for instructions such as "draw pattern to unlock", the next alarm, and charging
- status. -->
- <LinearLayout
- android:orientation="horizontal"
+ <TextView android:id="@+id/timeDisplayForeground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:gravity="center"
- >
- <TextView
- android:id="@+id/statusSep"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dip"
- android:layout_marginRight="5dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- />
- <TextView
- android:id="@+id/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="17sp"
- android:drawablePadding="4dip"
- />
- </LinearLayout>
-
- <!-- fill space between header and button below -->
- <View
- android:layout_weight="1.0"
- android:layout_width="match_parent"
- android:layout_height="0dip"
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:layout_marginBottom="6dip"
+ android:layout_alignLeft="@id/timeDisplayBackground"
+ android:layout_alignTop="@id/timeDisplayBackground"
+ android:textColor="@color/lockscreen_clock_foreground"
/>
- <!-- footer -->
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dip"
- >
+ </com.android.internal.widget.DigitalClock>
- <!-- option 1: a single emergency call button -->
- <RelativeLayout android:id="@+id/footerNormal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="left"
- >
- <Button android:id="@+id/emergencyCallAlone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- />
- </RelativeLayout>
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_gravity="right"
+ />
- <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
- <LinearLayout android:id="@+id/footerForgotPattern"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="left"
- >
- <Button android:id="@+id/forgotPattern"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/Widget.Button.Transparent"
- android:visibility="invisible"
- />
- <Button android:id="@+id/emergencyCallTogether"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- />
- </LinearLayout>
- </FrameLayout>
+ <TextView
+ android:id="@+id/alarm_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_gravity="right"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:layout_gravity="right"
+ />
+
+ <!-- TODO: remove hard coded height since layout_rowWeight doesn't seem to be working -->
+ <Space
+ android:layout_height="43dip"
+ android:layout_gravity="fill"
+ android:layout_rowWeight="1" android:layout_columnWeight="1" />
+
+ <TextView android:id="@+id/carrier"
+ android:layout_gravity="right"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ />
+
+ <LinearLayout
+ style="?android:attr/buttonBarStyle"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right">
+
+ <Button android:id="@+id/emergencyCallButton"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_gravity="right"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:text="@string/lockscreen_emergency_call"
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
+ android:drawablePadding="0dip"
+ />
+
+ <Button android:id="@+id/forgotPatternButton"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_gravity="right"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:text="@string/lockscreen_forgot_pattern_button_text"
+ android:drawableLeft="@drawable/lockscreen_forgot_password_button"
+ android:drawablePadding="0dip"
+ />
</LinearLayout>
- <!-- right side: lock pattern -->
+ <!-- Column 1: lock pattern -->
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dip"
+ android:layout_marginRight="8dip"
+ android:layout_marginBottom="8dip"
+ android:layout_marginLeft="8dip"
+ android:layout_rowSpan="7"/>
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
+</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 15f2afb..774f830 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -20,213 +20,155 @@
<!-- This is the screen that shows the 9 circle unlock widget and instructs
the user how to unlock their device, or make an emergency call. This
is the portrait layout. -->
-<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
+<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
- <TextView
- android:id="@+id/carrier"
+
+ <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ android:layout_marginBottom="18dip"
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+ android:layout_gravity="right">
+
+ <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+ top of the other. Hence the redundant layout... -->
+ <TextView android:id="@+id/timeDisplayBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_marginTop="6dip"
- android:layout_alignParentRight="true"
- android:layout_marginRight="8dip"
- android:layout_toRightOf="@+id/time"
android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="right|bottom"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_background"
/>
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
+ <TextView android:id="@+id/timeDisplayForeground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginTop="15dip"
- android:layout_marginLeft="20dip"
- android:layout_marginBottom="8dip"
- >
+ android:singleLine="true"
+ android:ellipsize="none"
+ android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="6dip"
+ android:textColor="@color/lockscreen_clock_foreground"
+ />
- <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
- top of the other. Hence the redundant layout... -->
- <TextView android:id="@+id/timeDisplayBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="56sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_background"
- />
+ </com.android.internal.widget.DigitalClock>
- <TextView android:id="@+id/timeDisplayForeground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="56sp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_foreground"
- />
-
- <TextView android:id="@+id/am_pm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/timeDisplayBackground"
- android:layout_alignBaseline="@id/timeDisplayBackground"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="18sp"
- android:layout_marginLeft="4dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_am_pm"
- />
-
- </com.android.internal.widget.DigitalClock>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_gravity="right"
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/time"
- android:layout_marginLeft="24dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
/>
- </RelativeLayout>
-
- <View
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- android:background="@android:drawable/divider_horizontal_dark"
- />
-
- <!-- used for instructions such as "draw pattern to unlock", the next alarm, and charging
- status. -->
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="0dip"
- android:layout_marginLeft="12dip"
- android:gravity="left"
- >
- <!-- TODO: Redo layout when we release on phones -->
<TextView
android:id="@+id/alarm_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
android:drawablePadding="4dip"
/>
- <TextView
- android:id="@+id/status1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- android:drawablePadding="4dip"
- />
- <TextView
- android:id="@+id/statusSep"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dip"
- android:layout_marginRight="5dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- />
- <TextView
- android:id="@+id/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="18sp"
- android:drawablePadding="4dip"
- />
+
</LinearLayout>
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_gravity="right"
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_gravity="right"
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:drawablePadding="4dip"
+ android:visibility="gone"
+ />
+
+ <!-- We need MATCH_PARENT here only to force the size of the parent to be passed to
+ the pattern view for it to compute its size. This is an unusual case, caused by
+ LockPatternView's requirement to maintain a square aspect ratio based on the width
+ of the screen. -->
<com.android.internal.widget.LockPatternView
android:id="@+id/lockPattern"
android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:layout_marginTop="2dip"
- android:aspect="@string/lock_pattern_view_aspect"
- />
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dip"
+ android:layout_marginRight="8dip"
+ android:layout_marginBottom="4dip"
+ android:layout_marginLeft="8dip"
+ android:layout_gravity="center|bottom"
+ android:layout_rowWeight="1"
+ />
- <!-- footer -->
- <FrameLayout
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <!-- Footer: an emergency call button and an initially hidden "Forgot pattern" button -->
+ <LinearLayout
+ android:orientation="horizontal"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
+ style="?android:attr/buttonBarStyle"
+ android:gravity="center"
+ android:weightSum="2">
- <!-- option 1: a single emergency call button -->
- <RelativeLayout android:id="@+id/footerNormal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <Button android:id="@+id/emergencyCallAlone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- />
+ <Button android:id="@+id/emergencyCallButton"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ style="?android:attr/buttonBarButtonStyle"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:text="@string/lockscreen_emergency_call"
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
+ android:drawablePadding="0dip"
+ />
- </RelativeLayout>
+ <Button android:id="@+id/forgotPatternButton"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ style="?android:attr/buttonBarButtonStyle"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ android:text="@string/lockscreen_forgot_pattern_button_text"
+ android:drawableLeft="@drawable/lockscreen_forgot_password_button"
+ android:drawablePadding="0dip"
+ />
- <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
- <LinearLayout android:id="@+id/footerForgotPattern"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- >
- <Button android:id="@+id/emergencyCallTogether"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:layout_marginLeft="4dip"
- android:layout_marginRight="2dip"
- android:text="@string/lockscreen_emergency_call"
- style="@style/Widget.Button.Transparent"
- android:drawableLeft="@drawable/ic_emergency"
- android:drawablePadding="8dip"
- />
- <Button android:id="@+id/forgotPattern"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1.0"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:layout_marginLeft="2dip"
- android:layout_marginRight="4dip"
- style="@style/Widget.Button.Transparent"
- android:visibility="invisible"
- />
- </LinearLayout>
+ </LinearLayout>
- </FrameLayout>
-
-</com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
+</GridLayout>
diff --git a/core/res/res/layout/number_picker.xml b/core/res/res/layout/number_picker.xml
index 807daf2..f2f524c 100644
--- a/core/res/res/layout/number_picker.xml
+++ b/core/res/res/layout/number_picker.xml
@@ -23,6 +23,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/numberPickerUpButtonStyle"
+ android:paddingTop="22dip"
+ android:paddingBottom="22dip"
android:contentDescription="@string/number_picker_increment_button" />
<EditText android:id="@+id/numberpicker_input"
@@ -34,6 +36,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/numberPickerDownButtonStyle"
+ android:paddingTop="22dip"
+ android:paddingBottom="22dip"
android:contentDescription="@string/number_picker_decrement_button" />
</merge>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 9742b94..2392618 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -46,7 +46,7 @@
<com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="?android:attr/actionBarStyle"
+ style="?android:attr/actionBarSplitStyle"
android:visibility="gone"
android:gravity="center"/>
</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 086acdd..19b861c 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -50,7 +50,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- style="?android:attr/actionBarStyle"
+ style="?android:attr/actionBarSplitStyle"
android:visibility="gone"
android:gravity="center"/>
</RelativeLayout>
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 7918a3f..790ac6b 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -23,36 +23,58 @@
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
+ android:orientation="vertical"
+ android:background="@color/transparent"
android:focusable="true"
- android:background="?android:attr/actionModeBackground"
android:descendantFocusability="afterDescendants">
- <RelativeLayout
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- >
+ android:background="?android:attr/actionModeBackground"
+ android:orientation="horizontal">
- <ImageView
- android:id="@+id/search_app_icon"
- android:layout_height="48dip"
- android:layout_width="48dip"
- android:layout_marginLeft="8dip"
- android:layout_marginRight="8dip"
- android:layout_gravity="center_vertical"
- android:layout_alignParentLeft="true"
- />
- <SearchView
- android:id="@+id/search_view"
- android:layout_width="match_parent"
+ <!-- Grouped to allow tapping on either item to exit search mode -->
+ <LinearLayout
+ android:id="@id/closeButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxWidth="600dip"
- android:iconifiedByDefault="false"
- android:layout_alignParentRight="true"
- android:layout_gravity="center_vertical|right"
+ android:orientation="horizontal"
+ android:focusable="true"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="?android:attr/homeAsUpIndicator"/>
+
+ <ImageView
+ android:id="@+id/search_app_icon"
+ android:layout_height="48dip"
+ android:layout_width="48dip"
+ android:layout_gravity="center_vertical"
/>
- </RelativeLayout>
+ </LinearLayout>
+ <!-- Actual search view with search icon, text field, close
+ and voice buttons -->
+ <SearchView
+ android:id="@+id/search_view"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxWidth="600dip"
+ android:iconifiedByDefault="false"
+ android:layout_gravity="center_vertical"
+ />
+
+ </LinearLayout>
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:src="@drawable/title_bar_shadow"/>
</view>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 99fdf5b..475aa59 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -74,7 +74,6 @@
android:id="@+id/search_app_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_marginRight="7dip"
android:layout_gravity="center_vertical"
android:src="?android:attr/searchViewSearchIcon"
/>
diff --git a/core/res/res/layout/select_dialog_item_holo.xml b/core/res/res/layout/select_dialog_item_holo.xml
index 396092e..0c700cf 100644
--- a/core/res/res/layout/select_dialog_item_holo.xml
+++ b/core/res/res/layout/select_dialog_item_holo.xml
@@ -26,7 +26,7 @@
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
diff --git a/core/res/res/layout/select_dialog_multichoice_holo.xml b/core/res/res/layout/select_dialog_multichoice_holo.xml
index 8027035..683151c 100644
--- a/core/res/res/layout/select_dialog_multichoice_holo.xml
+++ b/core/res/res/layout/select_dialog_multichoice_holo.xml
@@ -18,7 +18,7 @@
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
diff --git a/core/res/res/layout/select_dialog_singlechoice_holo.xml b/core/res/res/layout/select_dialog_singlechoice_holo.xml
index cab519f..52782d0 100644
--- a/core/res/res/layout/select_dialog_singlechoice_holo.xml
+++ b/core/res/res/layout/select_dialog_singlechoice_holo.xml
@@ -18,7 +18,7 @@
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml
new file mode 100644
index 0000000..ae661ce
--- /dev/null
+++ b/core/res/res/layout/ssl_certificate.xml
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:id="@+id/body"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <!-- Placeholder for the success message or one or more warnings -->
+ <LinearLayout
+ android:id="@+id/placeholder"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_marginTop="12dip"
+ android:orientation="vertical" />
+
+ <!-- Dialog-title line separator -->
+ <ImageView
+ android:id="@+id/title_separator"
+ android:src="@android:drawable/divider_horizontal_dark"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scaleType="fitXY"
+ android:layout_weight="1"
+ android:gravity="fill_horizontal"
+ android:layout_marginRight="20dip"
+ android:layout_marginLeft="20dip"
+ android:layout_marginBottom="12dip" />
+
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- Issued to: -->
+ <TextView
+ android:id="@+id/issued_to_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/issued_to"
+ android:textStyle="bold"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Common name: -->
+ <TextView
+ android:id="@+id/to_common_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/common_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/to_common"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Organization: -->
+ <TextView
+ android:id="@+id/to_org_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/org_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/to_org"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Organizational unit: -->
+ <TextView
+ android:id="@+id/to_org_unit_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/to_org_unit"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+
+ <!-- Issued by: -->
+ <TextView
+ android:id="@+id/issued_to_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/issued_by"
+ android:textStyle="bold"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Common name: -->
+ <TextView
+ android:id="@+id/by_common_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/common_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/by_common"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Organization: -->
+ <TextView
+ android:id="@+id/by_org_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/org_name"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/by_org"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Organizational unit: -->
+ <TextView
+ android:id="@+id/by_org_unit_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/org_unit"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/by_org_unit"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+
+ <!-- Validity Dates: -->
+ <TextView
+ android:id="@+id/validity_header"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/validity_period"
+ android:textStyle="bold"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Issued On: -->
+ <TextView
+ android:id="@+id/issued_on_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/issued_on"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/issued_on"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="10dip" />
+
+ <!-- Expires On: -->
+ <TextView
+ android:id="@+id/expires_on_header"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/expires_on"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip" />
+
+ <TextView
+ android:id="@+id/expires_on"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="left"
+ android:layout_marginLeft="20dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginBottom="12dip" />
+
+ </TableLayout>
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/layout/status_bar_latest_event_content.xml b/core/res/res/layout/status_bar_latest_event_content.xml
index 676c38b..0dc6741 100644
--- a/core/res/res/layout/status_bar_latest_event_content.xml
+++ b/core/res/res/layout/status_bar_latest_event_content.xml
@@ -1,4 +1,5 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
@@ -8,41 +9,9 @@
android:background="@drawable/notify_panel_notification_icon_bg"
android:scaleType="center"
/>
- <LinearLayout
- android:layout_width="0dp"
+ <include layout="@layout/status_bar_latest_event_content_large_icon"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingLeft="16dp"
- >
- <TextView android:id="@+id/title"
- android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"
- android:layout_marginBottom="-3dp"
- />
- <TextView android:id="@+id/text"
- android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginTop="-2dp"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"
- />
- </LinearLayout>
- <TextView android:id="@+id/info"
- android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:gravity="center_vertical"
- android:paddingLeft="8dp"
+ android:layout_gravity="center"
/>
</LinearLayout>
-
diff --git a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
index ebdaaa3..d937392 100644
--- a/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
+++ b/core/res/res/layout/status_bar_latest_event_content_large_icon.xml
@@ -1,50 +1,65 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/status_bar_latest_event_content_large_icon"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
>
- <LinearLayout
- android:layout_width="0dp"
+ <TextView android:id="@+id/title"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingLeft="16dp"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ />
+ <TextView android:id="@+id/text2"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-2dp"
+ android:layout_marginBottom="-2dp"
+ android:singleLine="true"
+ android:fadingEdge="horizontal"
+ android:ellipsize="marquee"
+ android:visibility="gone"
+ android:alpha="0.7"
+ />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:alpha="0.7"
>
- <TextView android:id="@+id/title"
- android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"
- android:layout_marginBottom="-3dp"
- />
<TextView android:id="@+id/text"
android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginTop="-2dp"
+ android:layout_gravity="center"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
/>
+ <TextView android:id="@+id/info"
+ android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="0"
+ android:singleLine="true"
+ android:gravity="center"
+ android:paddingLeft="8dp"
+ />
+ <ImageView android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_weight="0"
+ android:scaleType="center"
+ android:paddingLeft="8dp"
+ />
</LinearLayout>
- <TextView android:id="@+id/info"
- android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:gravity="center_vertical"
- android:paddingLeft="4dp"
- android:paddingRight="4dp"
- />
- <ImageView android:id="@+id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:layout_marginBottom="13dip"
- android:scaleType="center"
- />
</LinearLayout>
-
diff --git a/core/res/res/layout/tab_indicator_holo.xml b/core/res/res/layout/tab_indicator_holo.xml
index 60c80e9..d5fc3f4 100644
--- a/core/res/res/layout/tab_indicator_holo.xml
+++ b/core/res/res/layout/tab_indicator_holo.xml
@@ -15,17 +15,17 @@
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dp"
+ android:layout_width="wrap_content"
android:layout_height="58dp"
- android:layout_weight="1"
- android:layout_marginLeft="-3dip"
- android:layout_marginRight="-3dip"
+ android:layout_weight="0"
android:paddingBottom="8dp"
android:background="@android:drawable/tab_indicator_holo">
<ImageView android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="3dp"
+ android:paddingRight="3dp"
android:layout_centerHorizontal="true" />
<TextView android:id="@+id/title"
@@ -33,6 +33,8 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
+ android:paddingLeft="3dp"
+ android:paddingRight="3dp"
style="?android:attr/tabWidgetStyle" />
</RelativeLayout>
diff --git a/core/res/res/values-af-rZA/arrays.xml b/core/res/res/values-af-rZA/arrays.xml
new file mode 100644
index 0000000..5bff0f4
--- /dev/null
+++ b/core/res/res/values-af-rZA/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>-30559482</item>
+ <item>22937506</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index cab43ac..78381a3 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -47,8 +47,7 @@
<skip />
<!-- no translation found for mmiError (5154499457739052907) -->
<skip />
- <!-- no translation found for mmiFdnError (5224398216385316471) -->
- <skip />
+ <string name="mmiFdnError" msgid="5224398216385316471">"Bewerking is beperk tot belbeperking-nommers."</string>
<!-- no translation found for serviceEnabled (8147278346414714315) -->
<skip />
<!-- no translation found for serviceEnabledFor (6856228140453471041) -->
@@ -71,6 +70,8 @@
<skip />
<!-- no translation found for invalidPin (3850018445187475377) -->
<skip />
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"Jou SIM-kaart is PUK-gesluit. Voer die PUK-kode in om dit te ontsluit."</string>
<!-- no translation found for needPuk2 (4526033371987193070) -->
<skip />
@@ -109,16 +110,12 @@
<string name="RestrictedChangedTitle" msgid="5592189398956187498">"Beperkte toegang het verander"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Datadiens word geblokkeer."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Nooddiens word geblokkeer."</string>
- <!-- outdated translation 2045364908281990708 --> <string name="RestrictedOnNormal" msgid="4953867011389750673">"Stem-/SMS-diens word geblokkeer."</string>
- <!-- no translation found for RestrictedOnAllVoice (1459318899842232234) -->
- <skip />
- <!-- no translation found for RestrictedOnSms (8314352327461638897) -->
- <skip />
- <!-- no translation found for RestrictedOnVoiceData (8244438624660371717) -->
- <skip />
- <!-- no translation found for RestrictedOnVoiceSms (1888588152792023873) -->
- <skip />
- <!-- outdated translation 4923139582141626159 --> <string name="RestrictedOnAll" msgid="2714924667937117304">"Alle stem-/SMS-dienste is geblokkeer."</string>
+ <string name="RestrictedOnNormal" msgid="4953867011389750673">"Stemdiens word geblokkeer."</string>
+ <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Alle stemdienste is geblokkeer."</string>
+ <string name="RestrictedOnSms" msgid="8314352327461638897">"SMS-diens word geblokkeer."</string>
+ <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Stem-/datadienste is geblokkeer."</string>
+ <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Stem-/SMS-dienste is geblokkeer."</string>
+ <string name="RestrictedOnAll" msgid="2714924667937117304">"Alle stem-/data-/SMS-dienste is geblokkeer."</string>
<!-- no translation found for serviceClassVoice (1258393812335258019) -->
<skip />
<!-- no translation found for serviceClassData (872456782077937893) -->
@@ -194,16 +191,12 @@
<!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
<skip />
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Te veel <xliff:g id="CONTENT_TYPE">%s</xliff:g> uitgevee."</string>
- <!-- no translation found for low_memory (2292820184396262278) -->
- <skip />
- <!-- no translation found for low_memory (6632412458436461203) -->
- <skip />
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Tabletberging is vol! Vee \'n klompie lêers uit om plek te maak."</string>
+ <!-- outdated translation 2292820184396262278 --> <string name="low_memory" product="default" msgid="6632412458436461203">"Tabletberging is vol! Vee \'n klompie lêers uit om plek te maak."</string>
<!-- no translation found for me (6545696007631404292) -->
<skip />
- <!-- no translation found for power_dialog (8545351420865202853) -->
- <skip />
- <!-- no translation found for power_dialog (1319919075463988638) -->
- <skip />
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tablet-opsies"</string>
+ <!-- outdated translation 8545351420865202853 --> <string name="power_dialog" product="default" msgid="1319919075463988638">"Tablet-opsies"</string>
<!-- no translation found for silent_mode (7167703389802618663) -->
<skip />
<!-- no translation found for turn_on_radio (3912793092339962371) -->
@@ -216,20 +209,14 @@
<skip />
<!-- no translation found for shutdown_progress (2281079257329981203) -->
<skip />
- <!-- no translation found for shutdown_confirm (3385745179555731470) -->
- <skip />
- <!-- no translation found for shutdown_confirm (649792175242821353) -->
- <skip />
- <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
- <skip />
- <!-- no translation found for recent_tasks_title (3691764623638127888) -->
- <skip />
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Jou tablet gaan nou afskakel."</string>
+ <!-- outdated translation 3385745179555731470 --> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Jou tablet gaan nou afskakel."</string>
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"Wil jy afskakel?"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"Onlangs"</string>
<!-- no translation found for no_recent_tasks (279702952298056674) -->
<skip />
- <!-- no translation found for global_actions (408477140088053665) -->
- <skip />
- <!-- no translation found for global_actions (2406416831541615258) -->
- <skip />
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Tablet-opsies"</string>
+ <!-- outdated translation 408477140088053665 --> <string name="global_actions" product="default" msgid="2406416831541615258">"Tablet-opsies"</string>
<!-- no translation found for global_action_lock (2844945191792119712) -->
<skip />
<!-- no translation found for global_action_power_off (4471879440839879722) -->
@@ -243,8 +230,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegtuigmodus"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegtuigmodus is AAN"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegtuigmodus is AF"</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
- <skip />
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<!-- no translation found for safeMode (2788228061547930246) -->
<skip />
<string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
@@ -256,7 +242,7 @@
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Lees en skryf jou SMS-, e-pos- en ander boodskappe."</string>
<!-- no translation found for permgrouplab_personalInfo (3519163141070533474) -->
<skip />
- <!-- outdated translation 5488050357388806068 --> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkte toegang tot jou kontakte en kalender wat op die foon gestoor is."</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Direkte toegang tot jou kontakte en kalender wat op die tablet gestoor is."</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Direkte toegang tot jou kontakte en kalender wat op die foon gestoor is."</string>
<!-- no translation found for permgrouplab_location (635149742436692049) -->
<skip />
@@ -280,15 +266,13 @@
<skip />
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Kenmerke net nodig vir programontwikkelaars."</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Stoor"</string>
- <!-- outdated translation 9203302214915355774 --> <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Lees die SD-kaart."</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Gebruik die USB-berging."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Lees die SD-kaart."</string>
<!-- no translation found for permlab_statusBar (7417192629601890791) -->
<skip />
<string name="permdesc_statusBar" msgid="1365473595331989732">"Laat program toe om die statusbalk te deaktiveer of stelselikone by te voeg of te verwyder."</string>
- <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
- <skip />
- <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
- <skip />
+ <string name="permlab_statusBarService" msgid="7247281911387931485">"statusbalk"</string>
+ <string name="permdesc_statusBarService" msgid="4097605867643520920">"Laat die program toe om die statusbalk te wees."</string>
<!-- no translation found for permlab_expandStatusBar (1148198785937489264) -->
<skip />
<string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Laat program toe om die statusbalk uit of in te vou."</string>
@@ -301,16 +285,20 @@
<!-- no translation found for permlab_receiveMms (8894700916188083287) -->
<skip />
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Laat program toe om MMS-boodskappe te ontvang en te verwerk. Kwaadwillige programme kan jou boodskappe monitor of dit uitvee sonder om dit aan jou te wys."</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<!-- no translation found for permlab_sendSms (5600830612147671529) -->
<skip />
<string name="permdesc_sendSms" msgid="1946540351763502120">"Laat program toe om SMS-boodskappe te stuur. Kwaadwillige programme kan jou geld kos deur boodskappe sonder jou bevestiging te stuur."</string>
<!-- no translation found for permlab_readSms (4085333708122372256) -->
<skip />
- <!-- outdated translation 3002170087197294591 --> <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Laat program toe om SMS-boodskappe te lees wat op jou foon of SIM-kaart gestoor is. Kwaadwillige programme kan dalk jou vertroulike boodskappe lees."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Laat program toe om SMS-boodskappe te lees wat op jou tablet of SIM-kaart gestoor is. Kwaadwillige programme kan dalk jou vertroulike boodskappe lees."</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Laat program toe om SMS-boodskappe te lees wat op jou foon of SIM-kaart gestoor is. Kwaadwillige programme kan dalk jou vertroulike boodskappe lees."</string>
<!-- no translation found for permlab_writeSms (6881122575154940744) -->
<skip />
- <!-- outdated translation 6299398896177548095 --> <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Laat program toe om SMS-boodskappe te stuur wat op jou foon of SIM-kaart gestoor is. Kwaadwillige programme kan jou boodskappe uitvee."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Laat program toe om te skryf aan SMS-boodskappe wat op jou tablet of SIM-kaart gestoor is. Kwaadwillige programme kan jou boodskappe uitvee."</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Laat program toe om SMS-boodskappe te stuur wat op jou foon of SIM-kaart gestoor is. Kwaadwillige programme kan jou boodskappe uitvee."</string>
<!-- no translation found for permlab_receiveWapPush (8258226427716551388) -->
<skip />
@@ -331,31 +319,29 @@
<!-- no translation found for permlab_changeConfiguration (8214475779521218295) -->
<skip />
<string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Laat \'n program toe om die huidige opstelling, soos die locale of algemene lettergrootte, te verander."</string>
- <!-- no translation found for permlab_enableCarMode (5684504058192921098) -->
- <skip />
- <!-- no translation found for permdesc_enableCarMode (5673461159384850628) -->
- <skip />
- <!-- no translation found for permlab_killBackgroundProcesses (8373714752793061963) -->
- <skip />
- <!-- no translation found for permdesc_killBackgroundProcesses (2908829602869383753) -->
- <skip />
- <!-- no translation found for permlab_forceStopPackages (1447830113260156236) -->
- <skip />
- <!-- no translation found for permdesc_forceStopPackages (7263036616161367402) -->
- <skip />
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"aktiveer motormodus"</string>
+ <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Laat \'n program toe om die motormodus te aktiveer."</string>
+ <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"stop agtergrondprosesse"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Laat \'n program toe om ander programme se agtergrondprosesse te stop, selfs al is daar nie min geheue nie."</string>
+ <string name="permlab_forceStopPackages" msgid="1447830113260156236">"dwing ander programme om te stop"</string>
+ <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Laat \'n program toe om ander programme te dwing om te stop."</string>
<!-- no translation found for permlab_forceBack (1804196839880393631) -->
<skip />
<string name="permdesc_forceBack" msgid="6534109744159919013">"Laat \'n program toe om enige aktiwiteit wat in die voorgrond is, te dwing om te sluit en terug te gaan. Behoort vir gewone programme nooit nodig te wees nie."</string>
<!-- no translation found for permlab_dump (1681799862438954752) -->
<skip />
<string name="permdesc_dump" msgid="2198776174276275220">"Laat program toe om interne status van die stelsel op te haal. Kwaadwillige programme kan \'n wye verskeidenheid private en beveiligde inligting ophaal wat hulle normaalweg nooit nodig sou hê nie."</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelike afskakeling"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Plaas die aktiwiteitbestuurder in \'n afsluitingstatus. Doen nie \'n volledige afsluiting nie."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Voorkom dat die gebruiker na \'n ander program oorskakel."</string>
<!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) -->
<skip />
- <!-- outdated translation 3228701938345388092 --> <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Laat \'n program toe om te monitor of te beheer hoe die stelsel handelinge laat loop. Kwaadwillige programme kan die stelsel volledig kompromitteer. Hierdie toestemming is net nodig vir ontwikkeling, en nooit vir gewone foongebruik nie."</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Laat \'n program toe om te monitor en te beheer hoe die stelsel handelinge laat loop. Kwaadwillige programme kan die stelsel heeltemal kompromitteer. Hierdie toestemming is net vir ontwikkeling nodig, nooit vir gewone gebruik nie."</string>
<!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) -->
<skip />
<string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Laat \'n program toe om \'n kennisgewing uit te saai dat \'n programpakket verwyder is. Kwaadwillige programme kan dit gebruik om enige ander programme wat loop, te stop."</string>
@@ -383,7 +369,7 @@
<string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Laat die skep van vensters toe wat bedoel is om deur die interne stelsel se gebruikerkoppelvlak gebruik gemaak te word. Nie vir gebruik deur normale programme nie."</string>
<!-- no translation found for permlab_systemAlertWindow (3372321942941168324) -->
<skip />
- <!-- outdated translation 5109622689323490558 --> <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Laat \'n program toe om stelselwaarskuwing-vensters te wys. Kwaadwillige programme kan die hele skerm van die foon oorneem."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Laat \'n program toe om stelselwaarskuwing-vensters te wys. Kwaadwillige programme kan die hele skerm oorneem."</string>
<!-- no translation found for permlab_setAnimationScale (2805103241153907174) -->
<skip />
<string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Laat \'n program toe om die globale animasiespoed (vinniger of stadiger animasies) te enige tyd te verander."</string>
@@ -392,7 +378,7 @@
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Laat programme toe om hul eie tokens te skep en te bestuur, wat hul normale Z-volgordes omseil. Behoort vir gewone programme nooit nodig te wees nie."</string>
<!-- no translation found for permlab_injectEvents (1378746584023586600) -->
<skip />
- <!-- outdated translation 3946098050410874715 --> <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Laat \'n program toe om sy eie invoergebeurtenisse (sleutel indruk, ens) aan ander programme te lewer. Kwaadwillige programme kan dit gebruik om die foon oor te neem."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Laat \'n program toe om sy eie invoergebeurtenisse (sleuteldrukke ens.) na ander toestelle te lewer. Kwaadwillige programme kan dit gebruik om die tablet oor te neem."</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Laat \'n program toe om sy eie invoergebeurtenisse (sleutel indruk, ens) aan ander programme te lewer. Kwaadwillige programme kan dit gebruik om die foon oor te neem."</string>
<!-- no translation found for permlab_readInputState (469428900041249234) -->
<skip />
@@ -405,10 +391,8 @@
<skip />
<!-- no translation found for permdesc_bindRemoteViews (2930855984822926963) -->
<skip />
- <!-- no translation found for permlab_bindDeviceAdmin (8704986163711455010) -->
- <skip />
- <!-- no translation found for permdesc_bindDeviceAdmin (8714424333082216979) -->
- <skip />
+ <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
+ <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Behoort nooit vir gewone programme nodig te wees nie."</string>
<!-- no translation found for permlab_setOrientation (3365947717163866844) -->
<skip />
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Laat \'n program toe om die skerm te enige tyd te draai. Behoort vir gewone programme nooit nodig te wees nie."</string>
@@ -438,23 +422,20 @@
<string name="permdesc_installPackages" msgid="526669220850066132">"Laat \'n program toe om nuwe of opgedateerde Android-pakkette te installeer. Kwaadwillige programme kan dit gebruik om nuwe programme met arbitrêr kragtige regte by te voeg."</string>
<!-- no translation found for permlab_clearAppCache (4747698311163766540) -->
<skip />
- <!-- outdated translation 7740465694193671402 --> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Laat \'n program toe om foonstoorspasie skoon te maak deur lêers in die programkasgids uit te vee. Toegang tot stelselprosesse is gewoonlik baie beperk."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Laat \'n program toe om tabletberging beskikbaar te stel deur lêers in die programkasgids uit te vee. Toegang tot stelselprosesse is gewoonlik baie beperk."</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Laat \'n program toe om foonstoorspasie skoon te maak deur lêers in die programkasgids uit te vee. Toegang tot stelselprosesse is gewoonlik baie beperk."</string>
- <!-- no translation found for permlab_movePackage (728454979946503926) -->
- <skip />
- <!-- no translation found for permdesc_movePackage (6323049291923925277) -->
- <skip />
- <!-- no translation found for permlab_readLogs (6615778543198967614) -->
- <skip />
- <!-- outdated translation 2257937955580475902 --> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Laat \'n program toe om van die stelsel se verskillende loglêers te lees. Dit maak dit moontlik om algemene inligting te ontdek oor wat jy met die foon doen, maar dit behoort nie enige persoonlike of private inligting te bevat nie."</string>
- <!-- outdated translation 2257937955580475902 --> <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Laat \'n program toe om van die stelsel se verskillende loglêers te lees. Dit maak dit moontlik om algemene inligting te ontdek oor wat jy met die foon doen, maar dit behoort nie enige persoonlike of private inligting te bevat nie."</string>
+ <string name="permlab_movePackage" msgid="728454979946503926">"Skuif programhulpbronne"</string>
+ <string name="permdesc_movePackage" msgid="6323049291923925277">"Laat \'n program toe om programhulpbronne van interne na eksterne media te skuif, en omgekeerd."</string>
+ <string name="permlab_readLogs" msgid="6615778543198967614">"lees sensitiewe logdata"</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Laat \'n program toe om die stelsel se verskeie loglêers te lees. Dit maak dit moontlik om algemene inligting te ontdek oor wat jy met die tablet doen en bevat potensieel persoonlike of private inligting."</string>
+ <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Laat \'n program toe om van die stelsel se verskillende loglêers te lees. Dit maak dit moontlik om algemene inligting te ontdek oor wat jy met die foon doen, wat potensieel persoonlike of private inligting kan bevat."</string>
<!-- no translation found for permlab_diagnostic (8076743953908000342) -->
<skip />
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Laat \'n program toe om enige hulpbron te lees en na toe te skryf wat deur die diag-groep besit word; byvoorbeeld lêers in /dev. Dit kan potensieel stelselstabiliteit en -sekuriteit beïnvloed. Dit behoort net gebruik word vir hardewarespesifieke diagnose deur die vervaardiger of operateur."</string>
<!-- no translation found for permlab_changeComponentState (79425198834329406) -->
<skip />
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Laat \'n program toe om te verander of \'n komponent van \'n ander program aktief is of nie. Kwaadwillige programme kan dit gebruik om belangrike foonvermoëns te deaktiveer. Wees versigtig met toestemmings, want dit is moontlik om programkomponente onbruikbaar, inkonsekwent, of onstabiel te maak."</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Laat \'n program toe om te verander of \'n komponent van \'n ander program aktief is of nie. Kwaadwillige programme kan dit gebruik om belangrike foonvermoëns te deaktiveer. Wees versigtig met toestemmings, want dit is moontlik om programkomponente onbruikbaar, inkonsekwent, of onstabiel te maak."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Laat \'n program toe om te verander of \'n ander programkomponent geaktiveer is of nie. Kwaadwillige programme kan dit gebruik om belangrike tabletvermoëns te deaktiveer. Wees versigtig met dié toestemming, want dit is moontlik om programkomponente onbruikbaar, inkonsekwent, of onstabiel te maak."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Laat \'n program toe om te verander of \'n ander programkomponent geaktiveer is of nie. Kwaadwillige programme kan dit gebruik om belangrike foonvermoëns te deaktiveer. Wees versigtig met dié toestemming, want dit is moontlik om programkomponente onbruikbaar, inkonsekwent, of onstabiel te maak."</string>
<!-- no translation found for permlab_setPreferredApplications (3393305202145172005) -->
<skip />
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Laat \'n program toe om jou voorkeurprogramme te verander. Dit kan kwaadwillige programme in staat stel om die programme wat loop, stilletjies te verander, en bestaande programme na te maak, sodat dit private data oor jou insamel."</string>
@@ -468,27 +449,33 @@
<string name="permdesc_writeGservices" msgid="6602362746516676175">"Laat \'n program toe om Google se dienstekaart te verander. Nie vir gebruik deur normale programme nie."</string>
<!-- no translation found for permlab_receiveBootCompleted (7776779842866993377) -->
<skip />
- <!-- outdated translation 698336728415008796 --> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Laat \'n program toe om homself te laat begin sodra die stelsel klaar geselflaai het. Dit kan maak dat dit langer vir die foon neem om te begin, en die program kan die foon stadiger maak omdat dit altyd aan die gang is."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Laat \'n program toe om self te begin sodra die stelsel klaar geselflaai het. Dit kan maak dat dit langer vir die tablet neem om te begin en die program toelaat om die algehele tablet stadiger te maak deurdat dit altyd loop."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Laat \'n program toe om homself te laat begin sodra die stelsel klaar geselflaai het. Dit kan maak dat dit langer vir die foon neem om te begin, en die program kan die foon stadiger maak omdat dit altyd aan die gang is."</string>
<!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
<skip />
- <!-- outdated translation 1920045289234052219 --> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Laat \'n program toe om taai uitsendings te stuur, wat bly voortbestaan nadat die uitsending klaar is. Kwaadwillige programme kan die foon stadig of onstabiel maak deur te veel geheue te gebruik."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Laat \'n program toe om klewerige uitsendings te stuur, wat bly voortbestaan nadat die uitsending klaar is. Kwaadwillige programme kan die tablet stadig of onstabiel maak deur te veroorsaak dat dit te veel geheue gebruik."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Laat \'n program toe om taai uitsendings te stuur, wat bly voortbestaan nadat die uitsending klaar is. Kwaadwillige programme kan die foon stadig of onstabiel maak deur te veel geheue te gebruik."</string>
<!-- no translation found for permlab_readContacts (6219652189510218240) -->
<skip />
- <!-- outdated translation 3371591512896545975 --> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Laat \'n program toe om al die kontakdata (adresse) te lees wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou data na ander mense te stuur."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Laat \'n program toe om al die kontak- (adres) data te lees wat op jou tablet gestoor is. Kwaadwillige programme kan dit gebruik om jou data na ander mense te stuur."</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Laat \'n program toe om al die kontakdata (adresse) te lees wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou data na ander mense te stuur."</string>
<!-- no translation found for permlab_writeContacts (644616215860933284) -->
<skip />
- <!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Laat \'n program toe om die kontakdata (adresse) te wysig wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou kontakdata uit te vee of dit te wysig."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Laat \'n program toe om die kontak- (adres) data te wysig wat op jou tablet gestoor is. Kwaadwillige programme kan dit gebruik om jou kontakdata uit te vee of te wysig."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Laat \'n program toe om die kontakdata (adresse) te wysig wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou kontakdata uit te vee of dit te wysig."</string>
- <!-- no translation found for permlab_readCalendar (6898987798303840534) -->
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
<skip />
- <!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Laat \'n program toe om al die kalendergebeurtenisse te lees wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou kalendergebeurtenisse na ander mense te stuur."</string>
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
+ <string name="permlab_readCalendar" msgid="6898987798303840534">"lees kalendergebeure"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Laat \'n program toe om al die kalendergebeurtenisse te lees wat op jou tablet gestoor is. Kwaadwillige programme kan dit gebruik om jou kalendergebeurtenisse na ander mense te stuur."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Laat \'n program toe om al die kalendergebeurtenisse te lees wat op jou foon gestoor is. Kwaadwillige programme kan dit gebruik om jou kalendergebeurtenisse na ander mense te stuur."</string>
- <!-- no translation found for permlab_writeCalendar (3894879352594904361) -->
- <skip />
- <!-- outdated translation 8674240662630003173 --> <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Laat \'n program toe om die kalendergebeurtenisse wat op jou foon gestoor is, te wysig. Kwaadwillige programme kan dit gebruik om jou kalenderdata uit te vee of dit te wysig."</string>
+ <string name="permlab_writeCalendar" msgid="3894879352594904361">"wysig of voeg kalendergebeurtenisse by en stuur e-pos aan gaste"</string>
+ <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Laat \'n program toe om gebeurtenisse op jou kalender te wysig of by te voeg, wat \'n e-pos na gaste kan stuur. Kwaadwillige programme kan dit gebruik om jou kalendergebeurtenisse uit te vee of te wysig of e-pos aan gaste te stuur."</string>
<!-- no translation found for permlab_accessMockLocation (8688334974036823330) -->
<skip />
<string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Skep skynligging-bronne vir die toets. Kwaadwillige programme kan dit gebruik om die ligging en/of status te oorheers wat deur regteligging-bronne soos GPS of netwerkverskaffers opgehaal word."</string>
@@ -499,11 +486,11 @@
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Skep skynligging-bronne vir toetsing. Kwaadwillige programme kan dit gebruik om die plek en/of status te oorheers wat opgegee word deur regteligging-hulpbronne soos GPS of netwerkverskaffers, of om jou ligging te kontroleer en dit dan by \'n eksterne bron aan te gee."</string>
<!-- no translation found for permlab_accessFineLocation (8116127007541369477) -->
<skip />
- <!-- outdated translation 7411213317434337331 --> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Verkry toegang tot liggingbronne soos die wêreldwye posisioneerstelsel op die foon, waar beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal waar jy is, en dit kan bykomende batterykrag gebruik."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Verkry toegang tot fyn liggingsbronne soos die Global Positioning System op die tablet, waar beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal waar jy is, en dit kan bykomende batterykrag gebruik."</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Verkry toegang tot liggingbronne soos die wêreldwye posisioneerstelsel op die foon, waar beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal waar jy is, en dit kan bykomende batterykrag gebruik."</string>
<!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) -->
<skip />
- <!-- outdated translation 8235655958070862293 --> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Gebruik growwe liggingbronne soos die sellulêre netwerk se databasis om \'n geskatte foonligging te bepaal, indien beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal min of meer waar jy is."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Gebruik growwe liggingsbronne soos die sellulêre netwerk se databasis om \'n geskatte tabletligging te bepaal, indien beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal min of meer waar jy is."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Gebruik growwe liggingbronne soos die sellulêre netwerk se databasis om \'n geskatte foonligging te bepaal, indien beskikbaar. Kwaadwillige programme kan dit gebruik om te bepaal min of meer waar jy is."</string>
<!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) -->
<skip />
@@ -517,46 +504,31 @@
<!-- no translation found for permlab_recordAudio (3876049771427466323) -->
<skip />
<string name="permdesc_recordAudio" msgid="6493228261176552356">"Laat program toe om die klankopneem-pad te verkry."</string>
- <!-- no translation found for permlab_camera (3616391919559751192) -->
- <skip />
- <!-- outdated translation 9013476258810982546 --> <string name="permdesc_camera" msgid="6004878235852154239">"Laat program toe om foto\'s te neem met die kamera. Dit laat die program toe om te eniger tyd beelde te vang wat die kamera sien."</string>
- <!-- no translation found for permlab_brick (2961292205764488304) -->
- <skip />
- <!-- no translation found for permlab_brick (8337817093326370537) -->
- <skip />
- <!-- outdated translation 5569526552607599221 --> <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Laat die program toe om die hele foon permanent te deaktiveer. Dit is baie gevaarlik."</string>
+ <string name="permlab_camera" msgid="3616391919559751192">"neem foto\'s en video\'s"</string>
+ <string name="permdesc_camera" msgid="6004878235852154239">"Laat program toe om foto\'s en video\'s met die kamera te neem. Dit laat die program toe om te enige tyd foto\'s te neem van wat die kamera sien."</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktiveer tablet permanent"</string>
+ <!-- outdated translation 2961292205764488304 --> <string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktiveer tablet permanent"</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Laat die program toe om die hele tablet permanent te deaktiveer. Dit is baie gevaarlik."</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"Laat die program toe om die hele foon permanent te deaktiveer. Dit is baie gevaarlik."</string>
- <!-- no translation found for permlab_reboot (3436634972561795002) -->
- <skip />
- <!-- no translation found for permlab_reboot (2898560872462638242) -->
- <skip />
- <!-- outdated translation 7914933292815491782 --> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Laat die program toe om die foon te dwing om te herselflaai."</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"dwing tablet om te herselflaai"</string>
+ <!-- outdated translation 3436634972561795002 --> <string name="permlab_reboot" product="default" msgid="2898560872462638242">"dwing tablet om te herselflaai"</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Laat die program toe om die tablet te dwing om te herselflaai."</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Laat die program toe om die foon te dwing om te herselflaai."</string>
<!-- no translation found for permlab_mount_unmount_filesystems (1761023272170956541) -->
<skip />
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Laat die program toe om lêerstelsels te heg of te ontheg vir verwyderbare berging."</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formateer eksterne berging"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Laat die program toe om die verwyderbare geheue te formateer."</string>
- <!-- no translation found for permlab_asec_access (3411338632002193846) -->
- <skip />
- <!-- no translation found for permdesc_asec_access (8820326551687285439) -->
- <skip />
- <!-- no translation found for permlab_asec_create (6414757234789336327) -->
- <skip />
- <!-- no translation found for permdesc_asec_create (2621346764995731250) -->
- <skip />
- <!-- no translation found for permlab_asec_destroy (526928328301618022) -->
- <skip />
- <!-- no translation found for permdesc_asec_destroy (2746706889208066256) -->
- <skip />
- <!-- no translation found for permlab_asec_mount_unmount (2456287623689029744) -->
- <skip />
- <!-- no translation found for permdesc_asec_mount_unmount (5934375590189368200) -->
- <skip />
- <!-- no translation found for permlab_asec_rename (7496633954080472417) -->
- <skip />
- <!-- no translation found for permdesc_asec_rename (2152829985238876790) -->
- <skip />
+ <string name="permlab_asec_access" msgid="3411338632002193846">"kry inligting oor interne berging"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Laat die program toe om inligting oor interne berging te kry."</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"skep interne berging"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Laat die program toe om interne berging te skep."</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"vernietig interne berging"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Laat die program toe om interne berging te vernietig."</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"heg/ontheg interne berging"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Laat die program toe om interne berging te heg/ontheg."</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"herbenoem interne berging"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Laat die program toe om interne berging te hernoem."</string>
<!-- no translation found for permlab_vibrate (7768356019980849603) -->
<skip />
<string name="permdesc_vibrate" msgid="2886677177257789187">"Laat die program toe om die vibrator te beheer."</string>
@@ -567,10 +539,8 @@
<skip />
<!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
<skip />
- <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
- <skip />
- <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
- <skip />
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"implementeer MTP-protokol"</string>
+ <string name="permdesc_accessMtp" msgid="6532961200486791570">"Laat toegang tot die kern-MTP-drywer toe om die MTP-USB-protokol te implementeer."</string>
<!-- no translation found for permlab_hardware_test (4148290860400659146) -->
<skip />
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Laat die program toe om verskeie randapparatuur te beheer, eksklusief vir hardewaretoetse."</string>
@@ -580,7 +550,7 @@
<!-- no translation found for permlab_callPrivileged (4198349211108497879) -->
<skip />
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Laat die program toe om enige foonnommer te bel, insluitend noodnommers, sonder jou inmenging. Kwaadwillige programme kan onnodige en onwettige oproepe na nooddienste maak."</string>
- <!-- outdated translation 5604848095315421425 --> <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"begin dadelik met CDMA-foonopstelling"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"begin direk met CDMA-tabletopstelling"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"begin dadelik met CDMA-foonopstelling"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Laat die program toe om CDMA-voorsiening te begin. Kwaadwillige programme kan CDMA-voorsiening onnodig laat begin"</string>
<!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
@@ -596,21 +566,17 @@
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Laat die program toe om die foonkenmerke van die toestel te beheer. \'n Program met hierdie toestemming kan van netwerk verwissel, die foonradio aan en af skakel, en dies meer, sonder om jou ooit in kennis te stel."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"lees foon se staat en identiteit"</string>
<string name="permdesc_readPhoneState" msgid="188877305147626781">"Laat die program toe om die foonkenmerke van die toestel te gebruik. \'n Program met hierdie toestemming kan die foonnommer en reeksnommer van hierdie foon bepaal, asook of \'n oproep aktief is, aan watter nommer die oproep gekoppel is, en so aan."</string>
- <!-- no translation found for permlab_wakeLock (1531731435011495015) -->
- <skip />
- <!-- no translation found for permlab_wakeLock (573480187941496130) -->
- <skip />
- <!-- outdated translation 7584036471227467099 --> <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Laat \'n program toe om te voorkom dat die foon slaap."</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"verhoed dat tablet slaap"</string>
+ <!-- outdated translation 1531731435011495015 --> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"verhoed dat tablet slaap"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Laat \'n program toe om te voorkom dat die tablet aan die slaap raak."</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Laat \'n program toe om te voorkom dat die foon slaap."</string>
- <!-- no translation found for permlab_devicePower (2787034722616350417) -->
- <skip />
- <!-- no translation found for permlab_devicePower (4928622470980943206) -->
- <skip />
- <!-- outdated translation 4577331933252444818 --> <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Laat die program toe om die foon aan of af te skakel."</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"skakel tablet aan of af"</string>
+ <!-- outdated translation 2787034722616350417 --> <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"skakel tablet aan of af"</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Laat die program toe om die tablet aan of af te skakel."</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Laat die program toe om die foon aan of af te skakel."</string>
<!-- no translation found for permlab_factoryTest (3715225492696416187) -->
<skip />
- <!-- outdated translation 8136644990319244802 --> <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Laat loop as \'n laevlak-vervaardigertoets, sodat volle toegang tot die foonhardeware verkry word. Net beskikbaar wanneer \'n foon in vervaardigertoets-modus loop."</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Laat loop as \'n laevlak-vervaardigertoets, sodat volle toegang tot die tablethardeware verkry word. Net beskikbaar wanneer \'n tablet in vervaardigertoetsmodus loop."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Laat loop as \'n laevlak-vervaardigertoets, sodat volle toegang tot die foonhardeware verkry word. Net beskikbaar wanneer \'n foon in vervaardigertoets-modus loop."</string>
<!-- no translation found for permlab_setWallpaper (6627192333373465143) -->
<skip />
@@ -621,21 +587,18 @@
<!-- no translation found for permlab_masterClear (2315750423139697397) -->
<skip />
<string name="permdesc_masterClear" msgid="5033465107545174514">"Laat \'n program toe om die stelsel heeltemal terug te laai na die oorspronklike instellings, en alle data, opstellings en geïnstalleerde programme uit te vee."</string>
- <!-- no translation found for permlab_setTime (2021614829591775646) -->
- <skip />
- <!-- no translation found for permdesc_setTime (209693136361006073) -->
- <skip />
- <!-- no translation found for permdesc_setTime (667294309287080045) -->
- <skip />
+ <string name="permlab_setTime" msgid="2021614829591775646">"stel tyd"</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Laat \'n program toe om die tablet se horlosietyd te verander."</string>
+ <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Laat \'n program toe om die foon se horlosietyd te verander."</string>
<!-- no translation found for permlab_setTimeZone (2945079801013077340) -->
<skip />
- <!-- outdated translation 1902540227418179364 --> <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Laat \'n program toe om die foon se tydsone te verander."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Laat \'n program toe om die tablet se tydsone te verander."</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Laat \'n program toe om die foon se tydsone te verander."</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"tree op as die AccountManagerService"</string>
<string name="permdesc_accountManagerService" msgid="6056903274106394752">"Laat \'n program toe om oproepe na AccountAuthenticators te maak"</string>
<!-- no translation found for permlab_getAccounts (4549918644233460103) -->
<skip />
- <!-- outdated translation 6839262446413155394 --> <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Laat \'n program toe om die lys rekeninge te kry wat aan die foon bekend is."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Laat \'n program toe om die lys van rekeninge wat aan die tablet bekend is, te kry."</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Laat \'n program toe om die lys rekeninge te kry wat aan die foon bekend is."</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"dien as rekeningstawer"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Laat \'n program toe om die rekeningstawingsvermoëns van die AccountManager te gebruik, insluitend om rekeninge te skep, en om hul wagwoorde te kry en te stel."</string>
@@ -654,11 +617,9 @@
<string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Laat \'n program toe om die APN-instellings te wysig, soos die instaanbediener en poort van enige APN."</string>
<!-- no translation found for permlab_changeNetworkState (958884291454327309) -->
<skip />
- <!-- outdated translation 6278115726355634395 --> <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Laat \'n program toe om die statusnetwerke-konnektiwiteit te verander."</string>
- <!-- no translation found for permlab_changeTetherState (2702121155761140799) -->
- <skip />
- <!-- no translation found for permdesc_changeTetherState (8905815579146349568) -->
- <skip />
+ <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Laat \'n program toe om die status van netwerk-konnektiwiteit te verander."</string>
+ <string name="permlab_changeTetherState" msgid="2702121155761140799">"Verander verbinde konnektiwiteit"</string>
+ <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Laat \'n program toe om die status van verbinde netwerk-konnektiwiteit te verander."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"verander agtergronddata-gebruik-instelling"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Laat \'n program toe om die instelling oor agtergronddatagebruik te verander."</string>
<!-- no translation found for permlab_accessWifiState (8100926650211034400) -->
@@ -671,19 +632,17 @@
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Laat \'n program toe om pakkies te ontvang wat nie direk aan jou toestel gestuur is nie. Dit kan handig wees wanneer jy dienste wat naby is, wil opspoor. Dit gebruik meer krag as die niemultisaai-modus."</string>
<!-- no translation found for permlab_bluetoothAdmin (1092209628459341292) -->
<skip />
- <!-- outdated translation 7256289774667054555 --> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Laat \'n program toe om die plaaslike Bluetooth-foon op te stel, en om afgeleë toestelle te ontdek en daarmee saam te bind."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Laat \'n program toe om die plaaslike Bluetooth-tablet op te stel en om afgeleë toestelle te ontdek en daarmee saam te bind."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Laat \'n program toe om die plaaslike Bluetooth-foon op te stel, en om afgeleë toestelle te ontdek en daarmee saam te bind."</string>
<!-- no translation found for permlab_bluetooth (8361038707857018732) -->
<skip />
- <!-- outdated translation 762515380679392945 --> <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Laat \'n program toe om die plaaslike Bluetooth-foon se opstelling te sien, en om verbindings met saamgebinde toestelle te bewerkstellig en te aanvaar."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Laat \'n program toe om die plaaslike Bluetooth-tablet se opstelling te sien en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Laat \'n program toe om die plaaslike Bluetooth-foon se opstelling te sien, en om verbindings met saamgebinde toestelle te bewerkstellig en te aanvaar."</string>
- <!-- no translation found for permlab_nfc (4423351274757876953) -->
- <skip />
- <!-- no translation found for permdesc_nfc (9171401851954407226) -->
- <skip />
+ <string name="permlab_nfc" msgid="4423351274757876953">"beheer kortveldkommunikasie"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Laat \'n program toe om te kommunikeer met kortveldkommunikasie- (NFC) merkers, kaarte en lesers."</string>
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<!-- no translation found for permlab_disableKeyguard (4977406164311535092) -->
<skip />
@@ -708,57 +667,45 @@
<string name="permdesc_readDictionary" msgid="1082972603576360690">"Laat \'n program toe om enige private woorde, name en frases wat die gebruiker in die gebruikerwoordeboek gestoor het, te lees."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"skryf na gebruikergedefinieerde woordeboek"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"Laat \'n program toe om nuwe woorde te skryf in die gebruikerwoordeboek."</string>
- <!-- outdated translation 8079403759001777291 --> <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"wysig/vee uit SD-kaart se inhoud"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"verander/vee uit USB-berging se inhoud"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"wysig/vee uit SD-kaart se inhoud"</string>
- <!-- outdated translation 6643963204976471878 --> <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Laat \'n program toe om na die SD-kaart te skryf."</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Laat \'n program toe om na die USB-berging te skryf."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Laat \'n program toe om na die SD-kaart te skryf."</string>
- <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"verander/vee uit interne mediabergingsinhoud"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Laat \'n program toe om die inhoud van die interne mediaberging te verander."</string>
+ <string name="permlab_cache_filesystem" msgid="5656487264819669824">"lees die kaslêerstelsel"</string>
+ <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Laat \'n program toe om die kaslêerstelsel te lees en te skryf."</string>
+ <string name="permlab_use_sip" msgid="5986952362795870502">"maak/ontvang internetoproepe"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Laat \'n program toe om die SIP-diens te gebruik om internetoproepe te maak/te ontvang."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
<skip />
- <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
<skip />
- <!-- no translation found for permlab_cache_filesystem (5656487264819669824) -->
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
<skip />
- <!-- no translation found for permdesc_cache_filesystem (1624734528435659906) -->
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
<skip />
- <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+ <string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
+ <string name="policydesc_limitPassword" msgid="9083400080861728056">"Beheer die lengte van en watter karakters in skermontsluit-wagwoorde gebruik kan word"</string>
+ <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitor die aantal verkeerde wagwoorde wat ingetik word wanneer die skerm ontsluit word, en sluit die tablet of vee al die tabletdata uit as te veel verkeerde wagwoorde ingetik word."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Moniter die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die foon of vee al die foon se data af as te veel verkeerde wagwoorde ingevoer word"</string>
+ <string name="policylab_resetPassword" msgid="2620077191242688955">"Wysig die wagwoord wat die skerm ontsluit"</string>
+ <string name="policydesc_resetPassword" msgid="5391240616981297361">"Wysig die wagwoord wat die skerm ontsluit"</string>
+ <string name="policylab_forceLock" msgid="2274085384704248431">"Sluit die skerm"</string>
+ <string name="policydesc_forceLock" msgid="5696964126226028442">"Beheer hoe en wanneer die skerm sluit"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"Vee alle data uit"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Vee die tablet se data sonder waarskuwing uit deur \'n fabrieksterugstelling te doen"</string>
+ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Vee die foon se data sonder waarskuwing uit deur \'n fabrieksterugstelling uit te voer"</string>
+ <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Stel die toestel se globale instaan"</string>
+ <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Stel die toestel se globale instaan wat gebruik moet word terwyl die beleid geaktiveer is. Net die eerste toesteladministrateur stel die effektiewe globale instaan op."</string>
+ <!-- outdated translation 2314569545488269564 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Stel wagwoord se vervaldatum"</string>
+ <!-- outdated translation 7276906351852798814 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheer hoe lank voordat wagwoord vir skermsluit verander moet word"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Stel bergingsenkripsie"</string>
+ <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vereis dat gestoorde programdata geënkripteer word"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
- <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
- <skip />
- <!-- no translation found for policylab_limitPassword (4497420728857585791) -->
- <skip />
- <!-- no translation found for policydesc_limitPassword (9083400080861728056) -->
- <skip />
- <!-- no translation found for policylab_watchLogin (914130646942199503) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin (933601759466308092) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin (7227578260165172673) -->
- <skip />
- <!-- no translation found for policylab_resetPassword (2620077191242688955) -->
- <skip />
- <!-- no translation found for policydesc_resetPassword (5391240616981297361) -->
- <skip />
- <!-- no translation found for policylab_forceLock (2274085384704248431) -->
- <skip />
- <!-- no translation found for policydesc_forceLock (5696964126226028442) -->
- <skip />
- <!-- no translation found for policylab_wipeData (3910545446758639713) -->
- <skip />
- <!-- no translation found for policydesc_wipeData (314455232799486222) -->
- <skip />
- <!-- no translation found for policydesc_wipeData (7669895333814222586) -->
- <skip />
- <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
- <skip />
- <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
- <skip />
- <!-- no translation found for policylab_expirePassword (885279151847254056) -->
- <skip />
- <!-- no translation found for policydesc_expirePassword (4844430354224822074) -->
- <skip />
- <!-- no translation found for policylab_encryptedStorage (8901326199909132915) -->
- <skip />
- <!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
<skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Tuis"</item>
@@ -824,11 +771,10 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Werkroeper"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Assistent"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <!-- no translation found for eventTypeCustom (7837586198458073404) -->
- <skip />
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Gepasmaakte"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"Verjaardag"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Herdenking"</string>
- <!-- outdated translation 5834288791948564594 --> <string name="eventTypeOther" msgid="7388178939010143077">"Gebeurtenis"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"Ander"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"Gepasmaakte"</string>
<string name="emailTypeHome" msgid="449227236140433919">"Tuis"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Werk"</string>
@@ -855,51 +801,36 @@
<string name="orgTypeWork" msgid="29268870505363872">"Werk"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"Ander"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"Gepasmaakte"</string>
- <!-- no translation found for relationTypeCustom (3542403679827297300) -->
- <skip />
- <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
- <skip />
- <!-- no translation found for relationTypeBrother (8757913506784067713) -->
- <skip />
- <!-- no translation found for relationTypeChild (1890746277276881626) -->
- <skip />
- <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
- <skip />
- <!-- no translation found for relationTypeFather (5228034687082050725) -->
- <skip />
- <!-- no translation found for relationTypeFriend (7313106762483391262) -->
- <skip />
- <!-- no translation found for relationTypeManager (6365677861610137895) -->
- <skip />
- <!-- no translation found for relationTypeMother (4578571352962758304) -->
- <skip />
- <!-- no translation found for relationTypeParent (4755635567562925226) -->
- <skip />
- <!-- no translation found for relationTypePartner (7266490285120262781) -->
- <skip />
- <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
- <skip />
- <!-- no translation found for relationTypeRelative (1799819930085610271) -->
- <skip />
- <!-- no translation found for relationTypeSister (1735983554479076481) -->
- <skip />
- <!-- no translation found for relationTypeSpouse (394136939428698117) -->
- <skip />
- <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
- <skip />
- <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
- <skip />
- <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
- <skip />
- <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
- <skip />
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Gepasmaakte"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"Assistent"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Broer"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Kind"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Plaaslike vennoot"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Vader"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Vriend"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Bestuurder"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Moeder"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"Ouer"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Vennoot"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Verwys deur"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Relatief"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Suster"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Eggenoot"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Gepasmaakte"</string>
+ <string name="sipAddressTypeHome" msgid="6093598181069359295">"Tuis"</string>
+ <string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
+ <string name="sipAddressTypeOther" msgid="4408436162950119849">"Ander"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Voer PIN-kode in"</string>
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
+ <skip />
<!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
<skip />
- <!-- no translation found for keyguard_password_enter_password_code (9138158344813213754) -->
- <skip />
- <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
- <skip />
+ <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Voer wagwoord in om te ontsluit"</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Voer PIN in om te ontsluit"</string>
<!-- no translation found for keyguard_password_wrong_pin_code (1295984114338107718) -->
<skip />
<!-- no translation found for keyguard_label_text (861796461028298424) -->
@@ -916,13 +847,11 @@
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Teken patroon om te ontsluit"</string>
<!-- no translation found for lockscreen_emergency_call (5347633784401285225) -->
<skip />
- <!-- no translation found for lockscreen_return_to_call (5244259785500040021) -->
- <skip />
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Keer terug na oproep"</string>
<!-- no translation found for lockscreen_pattern_correct (9039008650362261237) -->
<skip />
<string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Jammer, probeer weer"</string>
- <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
- <skip />
+ <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Jammer, probeer weer"</string>
<string name="lockscreen_plugged_in" msgid="613343852842944435">"Laai (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
<string name="lockscreen_charged" msgid="4938930459620989972">"Gehef."</string>
<string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -930,15 +859,15 @@
<skip />
<!-- no translation found for lockscreen_missing_sim_message_short (7381499217732227295) -->
<skip />
- <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
- <skip />
- <!-- no translation found for lockscreen_missing_sim_message (2186920585695169078) -->
- <skip />
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet nie."</string>
+ <!-- outdated translation 151659196095791474 --> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in tablet nie."</string>
<!-- no translation found for lockscreen_missing_sim_instructions (8874620818937719067) -->
<skip />
- <!-- no translation found for emergency_calls_only (6733978304386365407) -->
- <!-- no translation found for emergency_calls_only (2485604591272668370) -->
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
<skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
+ <string name="emergency_calls_only" msgid="6733978304386365407">"Net noodoproepe"</string>
<!-- no translation found for lockscreen_network_locked_message (143389224986028501) -->
<skip />
<!-- no translation found for lockscreen_sim_puk_locked_message (7441797339976230) -->
@@ -949,12 +878,9 @@
<!-- no translation found for lockscreen_sim_unlock_progress_dialog_message (595323214052881264) -->
<skip />
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd geteken. "\n\n"Probeer weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
- <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
- <skip />
- <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
- <skip />
- <!-- no translation found for lockscreen_failed_attempts_almost_glogin (8687762517114904651) -->
- <skip />
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Jy het jou wagwoord <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd ingevoer. "\n\n"Probeer asseblief weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Jy het jou PIN <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd ingevoer. "\n\n"Probeer weer oor <xliff:g id="NUMBER_1">%d</xliff:g> sekondes."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd geteken. Na nog <xliff:g id="NUMBER_1">%d</xliff:g> onsuksesvolle pogings sal jy gevra word om jou tablet met jou Google-aanmeldnaam te ontsluit."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer verkeerd geteken. Na <xliff:g id="NUMBER_1">%d</xliff:g>meer onsuksesvolle pogings sal jy gevra word om jou foon met jou Google-aanmeldnaam te ontsluit."\n\n" Probeer weer oor <xliff:g id="NUMBER_2">%d</xliff:g> sekondes."</string>
<!-- no translation found for lockscreen_too_many_failed_attempts_countdown (6251480343394389665) -->
<skip />
@@ -975,18 +901,12 @@
<!-- no translation found for lockscreen_glogin_account_recovery_hint (8253152905532900548) -->
<skip />
<string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Kontroleer tans..."</string>
- <!-- no translation found for lockscreen_unlock_label (737440483220667054) -->
- <skip />
- <!-- no translation found for lockscreen_sound_on_label (9068877576513425970) -->
- <skip />
- <!-- no translation found for lockscreen_sound_off_label (996822825154319026) -->
- <skip />
- <!-- no translation found for password_keyboard_label_symbol_key (992280756256536042) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alpha_key (8001096175167485649) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alt_key (1284820942620288678) -->
- <skip />
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"Ontsluit"</string>
+ <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Klank aan"</string>
+ <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Klank af"</string>
+ <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
+ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
+ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<!-- no translation found for factorytest_failed (5410270329114212041) -->
@@ -1001,31 +921,21 @@
<!-- no translation found for save_password_label (6860261758665825069) -->
<skip />
<string name="double_tap_toast" msgid="1068216937244567247">"Wenk: dubbeltik om in en uit te zoem."</string>
- <!-- no translation found for autofill_this_form (1272247532604569872) -->
- <skip />
- <!-- no translation found for setup_autofill (8154593408885654044) -->
- <skip />
- <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
- <skip />
- <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
- <skip />
- <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
- <skip />
- <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
- <skip />
+ <string name="autofill_this_form" msgid="1272247532604569872">"Outo-invul"</string>
+ <string name="setup_autofill" msgid="8154593408885654044">"Stel outo-invul op"</string>
+ <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lees blaaier se geskiedenis en boekmerke"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Laat die program toe om al die URL\'e te lees wat die blaaier besoek het, asook al die blaaier se boekmerke."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skryf blaaier se geskiedenis en boekmerke"</string>
- <!-- outdated translation 945571990357114950 --> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Laat \'n program toe om die blaaier se geskiedenis of gestoorde boekmerke op die foon te wysig. Kwaadwillige programme kan dit gebruik om jou blaaier se data uit te vee of dit te wysig."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Laat \'n program toe om die blaaier se geskiedenis of gestoorde boekmerke op jou tablet te wysig. Kwaadwillige programme kan dit gebruik om jou blaaier se data uit te vee of te wysig."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Laat \'n program toe om die blaaier se geskiedenis of gestoorde boekmerke op die foon te wysig. Kwaadwillige programme kan dit gebruik om jou blaaier se data uit te vee of dit te wysig."</string>
- <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
- <skip />
- <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
- <skip />
- <!-- no translation found for permlab_writeGeolocationPermissions (4715212655598275532) -->
- <skip />
- <!-- no translation found for permdesc_writeGeolocationPermissions (4011908282980861679) -->
- <skip />
+ <string name="permlab_setAlarm" msgid="5924401328803615165">"stel alarm in wekker"</string>
+ <string name="permdesc_setAlarm" msgid="5966966598149875082">"Laat die program toe om \'n alarm te stel in \'n geïnstalleerde wekkerprogram. Sommige wekkerprogramme sal dalk nie hierdie kenmerk implementeer nie."</string>
+ <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Wysig blaaier se geoligging-toestemmings"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Laat \'n program toe om die blaaier se geoligging-toestemmings te wysig. Kwaadwillige programme kan dit gebruik om liggingsinligting na arbitrêre webwerwe te stuur."</string>
<!-- no translation found for save_password_message (767344687139195790) -->
<skip />
<!-- no translation found for save_password_notnow (6389675316706699758) -->
@@ -1065,11 +975,11 @@
<item quantity="one" msgid="9150797944610821849">"1 uur gelede"</item>
<item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> uur gelede"</item>
</plurals>
- <!-- no translation found for last_num_days:other (3069992808164318268) -->
- <!-- no translation found for last_month (3959346739979055432) -->
- <skip />
- <!-- no translation found for older (5211975022815554840) -->
- <skip />
+ <plurals name="last_num_days">
+ <item quantity="other" msgid="3069992808164318268">"Afgelope <xliff:g id="COUNT">%d</xliff:g> dae"</item>
+ </plurals>
+ <string name="last_month" msgid="3959346739979055432">"Verlede maand"</string>
+ <string name="older" msgid="5211975022815554840">"Ouer"</string>
<plurals name="num_days_ago">
<item quantity="one" msgid="861358534398115820">"gister"</item>
<item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> dae gelede"</item>
@@ -1171,22 +1081,17 @@
<skip />
<!-- no translation found for paste (5629880836805036433) -->
<skip />
- <!-- no translation found for pasteDisabled (7259254654641456570) -->
- <skip />
+ <string name="pasteDisabled" msgid="7259254654641456570">"Niks om te plak nie"</string>
<!-- no translation found for copyUrl (2538211579596067402) -->
<skip />
- <!-- no translation found for selectTextMode (6738556348861347240) -->
- <skip />
- <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
- <skip />
+ <string name="selectTextMode" msgid="6738556348861347240">"Kies teks..."</string>
+ <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekskeuse"</string>
<string name="inputMethod" msgid="1653630062304567879">"Invoermetode"</string>
- <!-- outdated translation 1672989176958581452 --> <string name="editTextMenuTitle" msgid="4909135564941815494">"Redigeer teks"</string>
+ <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksaksies"</string>
<!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
<skip />
- <!-- no translation found for low_internal_storage_view_text (4231085657068852042) -->
- <skip />
- <!-- no translation found for low_internal_storage_view_text (635106544616378836) -->
- <skip />
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tabletbergingspasie raak nou min."</string>
+ <!-- outdated translation 4231085657068852042 --> <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Tabletbergingspasie raak nou min."</string>
<!-- no translation found for ok (5970060430562524910) -->
<skip />
<!-- no translation found for cancel (6442560571259935130) -->
@@ -1196,8 +1101,7 @@
<!-- no translation found for no (5141531044935541497) -->
<skip />
<string name="dialog_alert_title" msgid="2049658708609043103">"Aandag"</string>
- <!-- no translation found for loading (1760724998928255250) -->
- <skip />
+ <string name="loading" msgid="1760724998928255250">"Laai tans..."</string>
<!-- no translation found for capital_on (1544682755514494298) -->
<skip />
<!-- no translation found for capital_off (6815870386972805832) -->
@@ -1233,38 +1137,25 @@
<string name="report" msgid="4060218260984795706">"Verslag"</string>
<!-- no translation found for wait (7147118217226317732) -->
<skip />
- <!-- no translation found for launch_warning_title (8323761616052121936) -->
- <skip />
- <!-- no translation found for launch_warning_replace (6202498949970281412) -->
- <skip />
- <!-- no translation found for launch_warning_original (188102023021668683) -->
- <skip />
+ <string name="launch_warning_title" msgid="8323761616052121936">"Program is herlei"</string>
+ <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> loop nou."</string>
+ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> is oorspronklik laat loop."</string>
<!-- no translation found for screen_compat_mode_scale (3202955667675944499) -->
<skip />
<!-- no translation found for screen_compat_mode_show (4013878876486655892) -->
<skip />
<!-- no translation found for screen_compat_mode_hint (2953716574198046484) -->
<skip />
- <!-- no translation found for smv_application (295583804361236288) -->
- <skip />
- <!-- no translation found for smv_process (5120397012047462446) -->
- <skip />
- <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
- <skip />
- <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
- <skip />
- <!-- no translation found for old_app_action (493129172238566282) -->
- <skip />
- <!-- no translation found for old_app_description (942967900237208466) -->
- <skip />
- <!-- no translation found for new_app_action (5472756926945440706) -->
- <skip />
- <!-- no translation found for new_app_description (6830398339826789493) -->
- <skip />
+ <string name="smv_application" msgid="295583804361236288">"Die program <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) het die selfopgelegde StrictMode-beleid geskend."</string>
+ <string name="smv_process" msgid="5120397012047462446">"Die proses <xliff:g id="PROCESS">%1$s</xliff:g> het die selfopgelegde StrictMode-beleid geskend."</string>
+ <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> loop"</string>
+ <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Kies wanneer om na program te wissel"</string>
+ <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Wissel programme?"</string>
+ <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"\'n Ander program loop reeds wat gestop moet word voor jy \'n nuwe een kan open."</string>
+ <string name="old_app_action" msgid="493129172238566282">"Keer terug na <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="old_app_description" msgid="942967900237208466">"Moenie die nuwe program begin nie."</string>
+ <string name="new_app_action" msgid="5472756926945440706">"Begin <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="new_app_description" msgid="6830398339826789493">"Stop die ou program sonder om te stoor."</string>
<!-- no translation found for sendText (5132506121645618310) -->
<skip />
<!-- no translation found for volume_ringtone (6885421406845734650) -->
@@ -1319,10 +1210,8 @@
<skip />
<!-- no translation found for sim_restart_button (4722407842815232347) -->
<skip />
- <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
- <skip />
- <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
- <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stel tyd"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string>
<!-- no translation found for date_time_set (5777075614321087758) -->
<skip />
<!-- no translation found for default_permission_group (2690160991405646128) -->
@@ -1331,40 +1220,36 @@
<skip />
<string name="perms_hide" msgid="7283915391320676226"><b>"Versteek"</b></string>
<string name="perms_show_all" msgid="2671791163933091180"><b>"Wys alle"</b></string>
- <!-- no translation found for usb_storage_activity_title (2399289999608900443) -->
- <skip />
+ <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-massaberging"</string>
<!-- no translation found for usb_storage_title (5901459041398751495) -->
<skip />
- <!-- outdated translation 2759542180575016871 --> <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Jy het jou foon aan jou rekenaar via USB gekoppel. Kies \"Heg\" as jy lêers tussen jou rekenaar en jou foon se SD-kaart wil kopieer."</string>
- <!-- outdated translation 2759542180575016871 --> <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Jy het jou foon aan jou rekenaar via USB gekoppel. Kies \"Heg\" as jy lêers tussen jou rekenaar en jou foon se SD-kaart wil kopieer."</string>
- <!-- no translation found for usb_storage_button_mount (1052259930369508235) -->
- <skip />
- <!-- no translation found for usb_storage_error_message (3276413764430468454) -->
- <skip />
- <!-- no translation found for usb_storage_error_message (120810397713773275) -->
- <skip />
+ <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Jy het aan jou rekenaar gekoppel via USB. Raak die knoppie hier onder as jy lêers tussen jou rekenaar en jou Android se USB-berging wil kopieer."</string>
+ <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Jy het aan jou rekenaar gekoppel via USB. Raak die knoppie hier onder as jy lêers tussen jou rekenaar en jou Android SD-kaart wil kopieer."</string>
+ <string name="usb_storage_button_mount" msgid="1052259930369508235">"Skakel USB-berging aan"</string>
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kon nie jou USB-berging vir USB-massaberging gebruik nie."</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kon nie jou SD-kaart vir USB-massaberging gebruik nie."</string>
<!-- no translation found for usb_storage_notification_title (8175892554757216525) -->
<skip />
<!-- no translation found for usb_storage_notification_message (7380082404288219341) -->
<skip />
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Skakel USB-geheue af"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Kies om USB-geheue af te skakel."</string>
- <!-- outdated translation 6014127947456185321 --> <string name="usb_storage_stop_title" msgid="660129851708775853">"Skakel USB-geheue af"</string>
- <!-- outdated translation 2390958966725232848 --> <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Voor jy USB-geheue afskakel, maak seker jy het dit op die USB-gasheer ontheg. Kies \"Skakel af\" om USB-geheue af te skakel."</string>
- <!-- outdated translation 2390958966725232848 --> <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voor jy USB-geheue afskakel, maak seker jy het dit op die USB-gasheer ontheg. Kies \"Skakel af\" om USB-geheue af te skakel."</string>
- <!-- outdated translation 1181858854166273345 --> <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Skakel af"</string>
- <!-- outdated translation 3746037090369246731 --> <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ons kon nie USB-geheue afskakel nie. Kontroleer of jy die USB-gasheer ontheg het, en probeer dan weer."</string>
- <!-- no translation found for dlg_confirm_kill_storage_users_title (963039033470478697) -->
+ <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-berging in gebruik"</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Voordat jy USB-berging afskakel, maak seker dat jy jou Android se USB-berging van jou rekenaar ontheg (\"uitgestoot\") het."</string>
+ <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Voordat jy die USB-berging afskakel, maak seker dat jy jou Android se SD-kaart uit die rekenaar ontheg (uitgeskiet) het."</string>
+ <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Skakel USB-berging af"</string>
+ <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kon nie USB-berging afskakel nie. Kontroleer of jy die USB-gasheer ontheg het, en probeer dan weer."</string>
+ <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Skakel USB-berging aan"</string>
+ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"As jy USB-berging aanskakel, sal sekere programme wat jy gebruik, stop en dalk nie beskikbaar wees nie tot jy USB-berging afskakel."</string>
+ <string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking het misluk"</string>
+ <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
<skip />
- <!-- no translation found for dlg_confirm_kill_storage_users_text (3202838234780505886) -->
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
<skip />
- <!-- no translation found for dlg_error_title (8048999973837339174) -->
- <skip />
- <!-- no translation found for dlg_ok (7376953167039865701) -->
- <skip />
- <!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formateer SD-kaart"</string>
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formateer USB-berging"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formateer SD-kaart"</string>
- <!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Is jy seker jy wil die SD-kaart formateer? Alle data op jou kaart sal verlore gaan."</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vee USB-berging uit, wat alle lêers wat daar gestoor word, sal uitvee? Handeling kan nie omgekeer word nie!"</string>
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Is jy seker jy wil die SD-kaart formateer? Alle data op jou kaart sal verlore gaan."</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Formaat"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB-ontfouter gekoppel"</string>
@@ -1375,36 +1260,34 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"kandidate"</u></string>
- <!-- outdated translation 5457603418970994050 --> <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Berei SD-kaart voor"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Berei USB-berging voor"</string>
<string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Berei SD-kaart voor"</string>
<string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontroleer vir foute."</string>
- <!-- outdated translation 780477838241212997 --> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Blanko SD-kaart"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Leë USB-berging"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Blanko SD-kaart"</string>
- <!-- outdated translation 3817704088027829380 --> <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD-kaart leeg of het nieondersteunde lêerstelsel."</string>
+ <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-berging leeg of het \'n nieondersteunde lêerstelsel."</string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kaart leeg of het nieondersteunde lêerstelsel."</string>
- <!-- outdated translation 6410723906019100189 --> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Beskadigde SD-kaart"</string>
+ <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Beskadigde USB-berging"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Beskadigde SD-kaart"</string>
- <!-- outdated translation 6902531775948238989 --> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD-kaart beskadig. Jy sal dit dalk moet herformateer."</string>
+ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-berging beskadig. Jy sal dit dalk moet herformateer."</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kaart beskadig. Jy sal dit dalk moet herformateer."</string>
- <!-- outdated translation 6872152882604407837 --> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD-kaart onverwags verwyder"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-berging onverwags verwyder"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kaart onverwags verwyder"</string>
- <!-- outdated translation 7260183293747448241 --> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ontheg SD-kaart voor jy dit uithaal, om dataverlies te vermy."</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ontheg USB-berging voordat jy dit verwyder om dataverlies te vermy."</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Ontheg SD-kaart voor jy dit uithaal, om dataverlies te vermy."</string>
- <!-- outdated translation 6729801130790616200 --> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD-kaart veilig om te verwyder"</string>
+ <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Veilig om USB-berging te verwyder"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-kaart veilig om te verwyder"</string>
- <!-- outdated translation 568841278138377604 --> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Jy kan SD-kaart veilig verwyder."</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Jy kan USB-berging veilig verwyder."</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Jy kan SD-kaart veilig verwyder."</string>
- <!-- outdated translation 8902518030404381318 --> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Verwyder SD-kaart"</string>
+ <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-berging is verwyder"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Verwyder SD-kaart"</string>
- <!-- outdated translation 3870120652983659641 --> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD-kaart verwyder. Sit \'n nuwe een in."</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-berging is verwyder. Voeg nuwe media in."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kaart verwyder. Sit \'n nuwe een in."</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Geen passende aktiwiteite gevind nie"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"dateer komponentgebruik-statistieke op"</string>
<string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Laat die wysiging van versamelde komponentgebruikstatistieke toe. Nie vir gebruik deur normale programme nie."</string>
- <!-- no translation found for permlab_copyProtectedData (1660908117394854464) -->
- <skip />
- <!-- no translation found for permdesc_copyProtectedData (537780957633976401) -->
- <skip />
+ <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Laat toe om verstek houerdiens op te roep om inhoud te kopieer. Nie vir gebruik deur normale programme nie."</string>
+ <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Laat toe om verstek houerdiens op te roep om inhoud te kopieer. Nie vir gebruik deur normale programme nie."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Klop twee keer vir zoembeheer"</string>
<string name="gadget_host_error_inflating" msgid="2613287218853846830">"Kon nie legstuk vergroot nie"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gaan"</string>
@@ -1412,17 +1295,13 @@
<string name="ime_action_send" msgid="2316166556349314424">"Stuur"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Volgende"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Klaar"</string>
- <!-- no translation found for ime_action_previous (1443550039250105948) -->
- <skip />
+ <string name="ime_action_previous" msgid="1443550039250105948">"Vorige"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Voer uit"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Skakel nommer"\n"met <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Skep kontak"\n"met <xliff:g id="NUMBER">%s</xliff:g>"</string>
- <!-- no translation found for grant_credentials_permission_message_header (6824538733852821001) -->
- <skip />
- <!-- no translation found for grant_credentials_permission_message_footer (3125211343379376561) -->
- <skip />
- <!-- no translation found for grant_permissions_header_text (2722567482180797717) -->
- <skip />
+ <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"Die volgende een of meer programme vra toestemming om nou en in die toekoms by jou rekening in te gaan."</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Wil jy hierdie versoek toestaan?"</string>
+ <string name="grant_permissions_header_text" msgid="2722567482180797717">"Toegangsversoek"</string>
<string name="allow" msgid="7225948811296386551">"Laat toe"</string>
<string name="deny" msgid="2081879885755434506">"Weier"</string>
<string name="permission_request_notification_title" msgid="5390555465778213840">"Toestemming versoek"</string>
@@ -1436,96 +1315,62 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Laag 2-tonnelprotokol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Voorafgedeelde sleutel gebaseer op L2TP/IPSec-VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikaat gebaseer op L2TP/IPSec-VPN"</string>
- <!-- no translation found for upload_file (2897957172366730416) -->
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
<skip />
- <!-- no translation found for no_file_chosen (6363648562170759465) -->
+ <!-- no translation found for vpn_title (5434034606697234123) -->
<skip />
- <!-- no translation found for reset (2448168080964209908) -->
+ <!-- no translation found for vpn_text (1610714069627824309) -->
<skip />
- <!-- no translation found for submit (1602335572089911941) -->
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
<skip />
- <!-- no translation found for car_mode_disable_notification_title (3164768212003864316) -->
- <skip />
- <!-- no translation found for car_mode_disable_notification_message (668663626721675614) -->
- <skip />
- <!-- no translation found for tethered_notification_title (3146694234398202601) -->
- <skip />
- <!-- no translation found for tethered_notification_message (3067108323903048927) -->
- <skip />
- <!-- no translation found for back_button_label (2300470004503343439) -->
- <skip />
- <!-- no translation found for next_button_label (1080555104677992408) -->
- <skip />
- <!-- no translation found for skip_button_label (1275362299471631819) -->
- <skip />
- <!-- no translation found for throttle_warning_notification_title (4890894267454867276) -->
- <skip />
- <!-- no translation found for throttle_warning_notification_message (2609734763845705708) -->
- <skip />
- <!-- no translation found for throttled_notification_title (6269541897729781332) -->
- <skip />
- <!-- no translation found for throttled_notification_message (4712369856601275146) -->
- <skip />
- <!-- no translation found for no_matches (8129421908915840737) -->
- <skip />
- <!-- no translation found for find_on_page (1946799233822820384) -->
- <skip />
- <!-- no translation found for matches_found:one (8167147081136579439) -->
- <!-- no translation found for matches_found:other (4641872797067609177) -->
- <!-- no translation found for action_mode_done (7217581640461922289) -->
- <skip />
- <!-- no translation found for progress_unmounting (535863554318797377) -->
- <skip />
- <!-- no translation found for progress_unmounting (5556813978958789471) -->
- <skip />
- <!-- no translation found for progress_erasing (4183664626203056915) -->
- <skip />
- <!-- no translation found for progress_erasing (2115214724367534095) -->
- <skip />
- <!-- no translation found for format_error (4320339096529911637) -->
- <skip />
- <!-- no translation found for format_error (1343380371925238343) -->
- <skip />
- <!-- no translation found for media_bad_removal (7960864061016603281) -->
- <skip />
- <!-- no translation found for media_checking (418188720009569693) -->
- <skip />
- <!-- no translation found for media_checking (7334762503904827481) -->
- <skip />
- <!-- no translation found for media_removed (7001526905057952097) -->
- <skip />
- <!-- no translation found for media_shared (5830814349250834225) -->
- <skip />
- <!-- no translation found for media_shared (5706130568133540435) -->
- <skip />
- <!-- no translation found for media_unknown_state (729192782197290385) -->
- <skip />
- <!-- no translation found for share (1778686618230011964) -->
- <skip />
- <!-- no translation found for find (4808270900322985960) -->
- <skip />
- <!-- no translation found for websearch (4337157977400211589) -->
- <skip />
- <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
- <skip />
- <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
- <skip />
- <!-- no translation found for gpsNotifMessage (1374718023224000702) -->
- <skip />
- <!-- no translation found for gpsVerifYes (2346566072867213563) -->
- <skip />
- <!-- no translation found for gpsVerifNo (1146564937346454865) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
- <skip />
- <!-- no translation found for sync_really_delete (8933566316059338692) -->
- <skip />
- <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
- <skip />
- <!-- no translation found for sync_do_nothing (8717589462945226869) -->
- <skip />
+ <string name="upload_file" msgid="2897957172366730416">"Kies lêer"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"Geen lêer gekies nie"</string>
+ <string name="reset" msgid="2448168080964209908">"Stel terug"</string>
+ <string name="submit" msgid="1602335572089911941">"Dien in"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Motormodus geaktiveer"</string>
+ <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Kies om motormodus te verlaat."</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"Verbinding of Wi-Fi-warmkol aktief"</string>
+ <string name="tethered_notification_message" msgid="3067108323903048927">"Raak om op te stel"</string>
+ <string name="back_button_label" msgid="2300470004503343439">"Terug"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"Volgende"</string>
+ <string name="skip_button_label" msgid="1275362299471631819">"Slaan oor"</string>
+ <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Hoë mobiele dataverbruik"</string>
+ <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Raak om meer te wete te kom oor mobiele datagebruik"</string>
+ <string name="throttled_notification_title" msgid="6269541897729781332">"Mobiele datalimiet oorskry"</string>
+ <string name="throttled_notification_message" msgid="4712369856601275146">"Raak om meer te wete te kom oor mobiele datagebruik"</string>
+ <string name="no_matches" msgid="8129421908915840737">"Geen passings nie"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"Vind op bladsy"</string>
+ <plurals name="matches_found">
+ <item quantity="one" msgid="8167147081136579439">"1 passing"</item>
+ <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g>"</item>
+ </plurals>
+ <string name="action_mode_done" msgid="7217581640461922289">"Klaar"</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Ontheg tans USB-berging..."</string>
+ <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Ontheg tans SD-kaart..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Vee tans USB-berging uit..."</string>
+ <string name="progress_erasing" product="default" msgid="2115214724367534095">"Vee tans SD-kaart uit..."</string>
+ <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Kon nie USB-berging uitvee nie."</string>
+ <string name="format_error" product="default" msgid="1343380371925238343">"Kon nie SD-kaart uitvee nie."</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"SD-kaart is verwyder voordat dit ontheg is."</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-berging word tans gekontroleer."</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"SD-kaart word tans gekontroleer."</string>
+ <string name="media_removed" msgid="7001526905057952097">"SD-kaart is verwyder."</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-berging word tans deur \'n rekenaar gebruik."</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kaart word tans deur \'n rekenaar gebruik."</string>
+ <string name="media_unknown_state" msgid="729192782197290385">"Eksterne media in onbekende toestand."</string>
+ <string name="share" msgid="1778686618230011964">"Deel"</string>
+ <string name="find" msgid="4808270900322985960">"Vind"</string>
+ <string name="websearch" msgid="4337157977400211589">"Websoektog"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Liggingsversoek van <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Liggingsversoek"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"Versoek deur <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"Ja"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"Nee"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"Uitveeperk is oorskry"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"Daar is <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> uitgeveede items vir <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, rekening <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Wat wil jy doen?"</string>
+ <string name="sync_really_delete" msgid="8933566316059338692">"Vee die items uit."</string>
+ <string name="sync_undo_deletes" msgid="8610996708225006328">"Ontdoen die uitvee."</string>
+ <string name="sync_do_nothing" msgid="8717589462945226869">"Doen vir eers niks."</string>
<!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
<skip />
<!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
@@ -1552,4 +1397,16 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am-rET/arrays.xml b/core/res/res/values-am-rET/arrays.xml
new file mode 100644
index 0000000..67e8b08
--- /dev/null
+++ b/core/res/res/values-am-rET/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>9145000</item>
+ <item>40489673</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b97bc7a..7a0441d 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -70,6 +70,8 @@
<skip />
<!-- no translation found for invalidPin (3850018445187475377) -->
<skip />
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"SIM ካርድዎ PUK-የተቆለፈ ነው።የPUK ኮዱን በመተየብ ይክፈቱት።"</string>
<!-- no translation found for needPuk2 (4526033371987193070) -->
<skip />
@@ -189,16 +191,12 @@
<!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
<skip />
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"በጣም ብዙ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ስርዞች።"</string>
- <!-- no translation found for low_memory (2292820184396262278) -->
- <skip />
- <!-- no translation found for low_memory (6632412458436461203) -->
- <skip />
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"የጡባዊ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
+ <!-- outdated translation 2292820184396262278 --> <string name="low_memory" product="default" msgid="6632412458436461203">"የጡባዊ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
<!-- no translation found for me (6545696007631404292) -->
<skip />
- <!-- no translation found for power_dialog (8545351420865202853) -->
- <skip />
- <!-- no translation found for power_dialog (1319919075463988638) -->
- <skip />
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"የጡባዊ አማራጮች"</string>
+ <!-- outdated translation 8545351420865202853 --> <string name="power_dialog" product="default" msgid="1319919075463988638">"የጡባዊ አማራጮች"</string>
<!-- no translation found for silent_mode (7167703389802618663) -->
<skip />
<!-- no translation found for turn_on_radio (3912793092339962371) -->
@@ -211,19 +209,14 @@
<skip />
<!-- no translation found for shutdown_progress (2281079257329981203) -->
<skip />
- <!-- no translation found for shutdown_confirm (3385745179555731470) -->
- <skip />
- <!-- no translation found for shutdown_confirm (649792175242821353) -->
- <skip />
- <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
- <skip />
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ጡባዊዎ ይዘጋል።"</string>
+ <!-- outdated translation 3385745179555731470 --> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ጡባዊዎ ይዘጋል።"</string>
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"መዝጋት ይፈልጋሉ?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"የቅርብ ጊዜ"</string>
<!-- no translation found for no_recent_tasks (279702952298056674) -->
<skip />
- <!-- no translation found for global_actions (408477140088053665) -->
- <skip />
- <!-- no translation found for global_actions (2406416831541615258) -->
- <skip />
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"የጡባዊ አማራጮች"</string>
+ <!-- outdated translation 408477140088053665 --> <string name="global_actions" product="default" msgid="2406416831541615258">"የጡባዊ አማራጮች"</string>
<!-- no translation found for global_action_lock (2844945191792119712) -->
<skip />
<!-- no translation found for global_action_power_off (4471879440839879722) -->
@@ -237,8 +230,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"የአውሮፕላን ሁነታ"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"የአውሮፕላንሁነታ በርቷል"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"የአውሮፕላንሁነታ ጠፍቷል"</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
- <skip />
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<!-- no translation found for safeMode (2788228061547930246) -->
<skip />
<string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
@@ -250,7 +242,7 @@
<string name="permgroupdesc_messages" msgid="7045736972019211994">"SMS ዎን፣ ኢሜይልዎን እና ሌላ መልዕክቶችዎን ያንብቡ እና ይፃፉ።"</string>
<!-- no translation found for permgrouplab_personalInfo (3519163141070533474) -->
<skip />
- <!-- outdated translation 5488050357388806068 --> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"በስልኩ ላይ ወደ ተከማቸው ዕውቂያዎችዎ እና የቀን መቁጠሪያዎበቀጥታ ይድረሱ"</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"በጡባዊዎ ላይ የተከማቹ እውቂያዎች እና ቀን መቁጠሪያጋ ቀጥታ ይድረሱ።"</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"በስልኩ ላይ ወደ ተከማቸው ዕውቂያዎችዎ እና የቀን መቁጠሪያዎበቀጥታ ይድረሱ"</string>
<!-- no translation found for permgrouplab_location (635149742436692049) -->
<skip />
@@ -274,7 +266,7 @@
<skip />
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"ባህሪያትለትግበራ ገንቢዎችብቻ ያስፈልጋሉ።"</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"ማከማቻ"</string>
- <!-- outdated translation 9203302214915355774 --> <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"SD ካርድ ድረስ"</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"የUSB ማከማቻ ድረስ።"</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"SD ካርድ ድረስ"</string>
<!-- no translation found for permlab_statusBar (7417192629601890791) -->
<skip />
@@ -293,16 +285,20 @@
<!-- no translation found for permlab_receiveMms (8894700916188083287) -->
<skip />
<string name="permdesc_receiveMms" msgid="4563346832000174373">"ትግበራ የMMS መልዕክቶችን ለማስኬድ እና ለመቀበል ይፈቅዳል።ተንኮል አዘም ትግበራዎች መልዕክቶን ይከታተላሉ ወይም ለእርስዎ ሳያሳዩ ይሰርዛሉ።"</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<!-- no translation found for permlab_sendSms (5600830612147671529) -->
<skip />
<string name="permdesc_sendSms" msgid="1946540351763502120">"ተንኮል አዘል ትግበራዎች ያለእርስዎ ማረጋገጫ ገንዘብ የሚያስወጣዎትንመልዕክቶች እየላኩ ነው።SMS መልዕክቶች ለመላክ ትግበራ ይፈቅዳል።"</string>
<!-- no translation found for permlab_readSms (4085333708122372256) -->
<skip />
- <!-- outdated translation 3002170087197294591 --> <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"ትግበራ በስ ልክዎ ወይም SIM ካርድ ላይ SMS መልዕክቶችን ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ሚስጥራዊ መልዕክቶችዎን ሊያነቡ ይችላሉ።"</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"ትግበራ በጡባዊዎ ወይም SIM ካርድዎ ላይ SMS መልዕክቶችን ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ሚስጥራዊ መልዕክቶችዎን ሊያነቡ ይችላሉ።"</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"ትግበራ በስ ልክዎ ወይም SIM ካርድ ላይ SMS መልዕክቶችን ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ሚስጥራዊ መልዕክቶችዎን ሊያነቡ ይችላሉ።"</string>
<!-- no translation found for permlab_writeSms (6881122575154940744) -->
<skip />
- <!-- outdated translation 6299398896177548095 --> <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">" ትግበራ በስልክዎ SIM ካርድ ላይ የተከማቹ የSMS መልዕክቶች ለመፃፍ ይፈቅዳል። ተንኮል አዘል ትግበራዎች መልዕክቶችዎን ሰርዘው ይሆናል።"</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"ትግበራ በጡባዊዎ SIM ካርድ ላይ የተከማቹ የSMS መልዕክቶች ለመፃፍ ይፈቅዳል። ተንኮል አዘል ትግበራዎች መልዕክቶችዎን ሰርዘው ይሆናል።"</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">" ትግበራ በስልክዎ SIM ካርድ ላይ የተከማቹ የSMS መልዕክቶች ለመፃፍ ይፈቅዳል። ተንኮል አዘል ትግበራዎች መልዕክቶችዎን ሰርዘው ይሆናል።"</string>
<!-- no translation found for permlab_receiveWapPush (8258226427716551388) -->
<skip />
@@ -335,13 +331,17 @@
<!-- no translation found for permlab_dump (1681799862438954752) -->
<skip />
<string name="permdesc_dump" msgid="2198776174276275220">"ትግበራ የስረዓት ውስጣዊ ሁኔታ ሰርስረው ሊያወጡ ይፈቅዳል። ተንኮል አዘል ትግበራዎች በፍፁም የማያስፈልጋቸውን የተለያዩ ሰፋ ያለ የግል እና የተጠበቀ መረጃ ሰርስረ ው ሊያወጡይችላሉ።"</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"ተጠቃሚው ከሌላ ትግበራ ከመቀየር ይከላከላል።"</string>
<!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) -->
<skip />
- <!-- outdated translation 3228701938345388092 --> <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"ትግበራ ስርዓት እንዴት እንቅስቃሴዎችን እንደሚያስነሳ ለመቆጣጠር እና ለመከታተል ይፈቅዳል።ተንኮል አዘል ትግበራዎች ስርዓቱን ሙሉ ለሙሉ ማመቻቸት ይችላል።ይህ ፈቃድ ለግንባታ ብቻ ያስፈልጋል፣በፍፁም ለመደበኛ ስልክ አጠቃቀም አያስፈልግም።"</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"ትግበራ ስርዓት እንዴት እንቅስቃሴዎችን እንደሚያስነሳ ለመቆጣጠር እና ለመከታተል ይፈቅዳል።ተንኮል አዘል ትግበራዎች ስርዓቱን ሙሉ ለሙሉ ማመቻቸት ይችላል።ይህ ፈቃድ ለግንባታ ብቻ ያስፈልጋል፣በፍፁም ለመደበኛ ስልክ አጠቃቀም አያስፈልግም።"</string>
<!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) -->
<skip />
<string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"ትግበራ የትግበ ራ አካታች ሲወገድ የቆየበትን ማሳወቂያ ለማሰራጨትይፈቅዳል። ተንኮል አዘል ትግበራዎች ማንኛውም በማሄድ ላይ ያለ ሌላ ትግበራ ለመዎች ሊጠቀም ይችላል።"</string>
@@ -369,7 +369,7 @@
<string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"በውስጥ ስርዓት ተጠቃሚ በየነገፅ ለመጠቀም የሚታሰብ ዊንዶውዝ መፍጠር ይፈቅዳል። ለመደበኛ ትግበራዎች ጥቅም አይደለም።"</string>
<!-- no translation found for permlab_systemAlertWindow (3372321942941168324) -->
<skip />
- <!-- outdated translation 5109622689323490558 --> <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"ትግበ ራ የስርዓት ማንቂያ ዊንዶውዝ ለማሳየት ይፈቅዳል። ተንኮል አዘል ትግበራዎች የስልኩን ጠቅላላ ማያ ሊቆጣጠሩት ይችላሉ።"</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"ትግበ ራ የስርዓት ማንቂያ ዊንዶውዝ ለማሳየት ይፈቅዳል። ተንኮል አዘል ትግበራዎች የስልኩን ጠቅላላ ማያ ሊቆጣጠሩት ይችላሉ።"</string>
<!-- no translation found for permlab_setAnimationScale (2805103241153907174) -->
<skip />
<string name="permdesc_setAnimationScale" msgid="7181522138912391988">"ትግበራ የአለም አቀፍ እነማ ፍጥነት(ፈጣን ወይም ቀርፋፋ እነማዎችን) በማንኛውም ጊዜ ለመለወጥ ይፈቅዳል።"</string>
@@ -378,7 +378,7 @@
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"ትግበራዎች የራሳቸውን ቶከኖች ለመፍጠር እና ለማደራጀት፣መደበኛ ፐ- አሰላለፋቸውን በጎን ለማለፍ ይፈቅዳሉ።ለመደበኛ ትግበራዎች በፍፁም አያስፈልጉም።"</string>
<!-- no translation found for permlab_injectEvents (1378746584023586600) -->
<skip />
- <!-- outdated translation 3946098050410874715 --> <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"ትግበራ የራሱን ግቤት ክስተት(ቁልፎች ተጫን፣ወዘተ)ለሌላ ትግበራዎች ለማድረስ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ስልኩን ለመቆጣጠር ይህን መጠቀም ይችላሉ።"</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"ትግበራ የራሱን ግቤት ክስተት(ቁልፎች ተጫን፣ወዘተ)ለሌላ ትግበራዎች ለማድረስ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ስልኩን ለመቆጣጠር ይህን መጠቀም ይችላሉ።"</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"ትግበራ የራሱን ግቤት ክስተት(ቁልፎች ተጫን፣ወዘተ)ለሌላ ትግበራዎች ለማድረስ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ስልኩን ለመቆጣጠር ይህን መጠቀም ይችላሉ።"</string>
<!-- no translation found for permlab_readInputState (469428900041249234) -->
<skip />
@@ -422,20 +422,20 @@
<string name="permdesc_installPackages" msgid="526669220850066132">"ትግበራ አዲስ ወይም የዘመነ የAndroid አካታቾች ለመጫን ይፈቅዳል። ተንኮል አዘል ትግበራዎች አዲስ ትግበራዎች በዘፈቀደ ኃይል ፈቃድ ለማከል ይህን መጠቀም ይችላሉ።"</string>
<!-- no translation found for permlab_clearAppCache (4747698311163766540) -->
<skip />
- <!-- outdated translation 7740465694193671402 --> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"ትግበራ ከመሸጎጫ ማውጫ ውስጥ ያሉፋይሎችንበመሰረዝ የስልክን ማከማቻ ነፃማድረግ ይፈቅዳል። አብዛኛውን ጊዜድረስ ለስርዓተ ሂደት በጣም የተከለከለ ነው።"</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"ትግበራ ከመሸጎጫ ማውጫ ውስጥ ያሉ ፋይሎችንበመሰረዝ የጡባዊን ማከማቻ ነፃማድረግ ይፈቅዳል። አብዛኛውን ጊዜ ለስርዓተ ሂደት ድረስ በጣም የተከለከለ ነው።"</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"ትግበራ ከመሸጎጫ ማውጫ ውስጥ ያሉፋይሎችንበመሰረዝ የስልክን ማከማቻ ነፃማድረግ ይፈቅዳል። አብዛኛውን ጊዜድረስ ለስርዓተ ሂደት በጣም የተከለከለ ነው።"</string>
<string name="permlab_movePackage" msgid="728454979946503926">"የትግበራ ንብረቶችን አዟዙር"</string>
<string name="permdesc_movePackage" msgid="6323049291923925277">"ትግበራ የትግበራ ንብረቶችን ከውስጥ ማህደረ መረጃ ወደ ውጪ እና የተገላቢጦሽ ለማዛወር ይፈቅዳል።"</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"ወሳኝ የማስታወሻ ውሂብ አንብብ"</string>
- <!-- outdated translation 8896449437464867766 --> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"ትግበራ ከስርዓቱ የተለያዩ የማስታወሻ ፋይሎች ውስጥ ለማንበብ ይፈቅዳል። ይህ ስለ ስልክዎ ምን እያደረጉበት እንደሆነ የብህታዊ ወይም የግል መረጃን ጨምሮ ጠቅላላ መረጃ ለማግኘት ይፈቅዳል።"</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"ትግበራ ከተለያዩ የስርዓት ማስታወሻዎች ፋይሎችን ለማንበብ ይፈቅዳል።ይህ በጡባዊው ምን እያደረጉ እንደሆነ ጠቅላላመረጃ ለማግኘት ይፈቅዳል፣ ነገር ግን ማንኛውም የግል ወይም የብሕትወት መረጃ መያዝ የለበትም።"</string>
<string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"ትግበራ ከስርዓቱ የተለያዩ የማስታወሻ ፋይሎች ውስጥ ለማንበብ ይፈቅዳል። ይህ ስለ ስልክዎ ምን እያደረጉበት እንደሆነ የብህታዊ ወይም የግል መረጃን ጨምሮ ጠቅላላ መረጃ ለማግኘት ይፈቅዳል።"</string>
<!-- no translation found for permlab_diagnostic (8076743953908000342) -->
<skip />
<string name="permdesc_diagnostic" msgid="3121238373951637049">"ትግበራ በዲያግ ቡድን ባለቤትነት ወደ አለማንኛውም ንብረት ለምሳሌ በ/dev ያሉ ፋይሎች ለማንበብ እና ለመፃፍ ይፈቅዳል። ይህ በመሰረቱ የስርዓት መረጋጋትን እና ደህንነትን ሊጎዳ ይችላል። ይህ ውስን የሀርድዌር-ተኮር ዲያግኖስቲክስ በአምራቹ ወይም ከዋኙ ብቻ መሆን አለበት።"</string>
<!-- no translation found for permlab_changeComponentState (79425198834329406) -->
<skip />
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"አንድ ትግበራ የሌላ ትግበራ ምንዝር ነቅቶ ወይም አልነቃ እንደሆነ ለመለወጥ ይፈቅዳል። ተንኮል አዘል ትግበራዎች አስፈላጊ የስልክ ችሎታዎችን ላለማንቃት ይህን መጠቀም ይችላሉ። የትግበራ ምዝሮችን በማይጠቅም፣ ወጥ ባልሆነ ወይም ባልተረጋጋ ሁኔታ ማግኘት እንደሚቻል፣ ጥንቃቄም በፈቃድ መጠቀም አለበት።"</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"አንድ ትግበራ የሌላ ትግበራ ምንዝር ነቅቶ ወይም አልነቃ እንደሆነ ለመለወጥ ይፈቅዳል። ተንኮል አዘል ትግበራዎች አስፈላጊ የስልክ ችሎታዎችን ላለማንቃት ይህን መጠቀም ይችላሉ። የትግበራ ምዝሮችን በማይጠቅም፣ ወጥ ባልሆነ ወይም ባልተረጋጋ ሁኔታ ማግኘት እንደሚቻል፣ ጥንቃቄም በፈቃድ መጠቀም አለበት።"</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"ትግበራ የሌላ ትግበራ ምንዝር ነቅቶ ወይም አልነቃ እንደሆነ ለመለወጥ ይፈቅዳል። ተንኮል አዘል ትግበራዎች አስፈላጊ የጡባዊ ችሎታዎችን ላለማንቃት ይህን መጠቀም ይችላሉ። የትግበራ ምዝሮችን በማይጠቅም፣ ወጥ ባልሆነ ወይም ባልተረጋጋ ሁኔታ ማግኘት እንደሚቻል፣በዚህ ፈቃድ ላይ ጥንቃቄ መደረግአለበት።"</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"ትግበራ የሌላ ትግበራ ምንዝር ነቅቶ ወይም አልነቃ እንደሆነ ለመለወጥ ይፈቅዳል። ተንኮል አዘል ትግበራዎች አስፈላጊ የስልክ ችሎታዎችን ላለማንቃት ይህን መጠቀም ይችላሉ። የትግበራ ምዝሮችን በማይጠቅም፣ ወጥ ባልሆነ ወይም ባልተረጋጋ ሁኔታ ማግኘት እንደሚቻል፣በዚህ ፈቃድ ላይ ጥንቃቄ መደረግአለበት።"</string>
<!-- no translation found for permlab_setPreferredApplications (3393305202145172005) -->
<skip />
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">" ትግበራ የእርስዎ ተመራጭ ትግበራዎችን ለቀይር ይፈቅዳል። ይህ ተንኮል አዘል ትግበራዎች በፀጥታ አሂድ ትግበራዎችን ለመለወጥ፣ያሉ ትግበራዎች የግል ውሂብ ከእርስዎ በማነፍነፍ ለመሰብሰብ ይፈቅዳል።"</string>
@@ -449,22 +449,30 @@
<string name="permdesc_writeGservices" msgid="6602362746516676175">"ትግበራ የGoogle ካርታ አገልግሎቶችን ለመቀየር ይፈቅዳል።ለመደበኛ ትግበራዎች ጥቅም አይደለም።"</string>
<!-- no translation found for permlab_receiveBootCompleted (7776779842866993377) -->
<skip />
- <!-- outdated translation 698336728415008796 --> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"ትግበራ ስርአቱ መነሳቱን ወዲያው እንደጨረሰ ራሱ እንዲጀምር ይፈቅዳል።ይህ ስልኩ ለመጀመር ረጅም ጊዜ እንዲፈጅ ሊያደርገው እና ትግበራው ሁልጊዜ በማሄድ ስልኩን በአጠቃላይ ለማዘግየት ይፈቅዳል።"</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"ትግበራ ስርአቱ ተነስቶወዲያው እንደጨረሰ ራሱ እንዲጀምር ይፈቅዳል።ይህ ጡባዊው ለመጀመር ረጅም ጊዜ እንዲፈጅ ሊያደርገው እና በአጠቃላይ ትግበራው ሁልጊዜ በማሄድ ጡባዊውንለማዘግየት ይፈቅዳል።"</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"ትግበራ ስርአቱ መነሳቱን ወዲያው እንደጨረሰ ራሱ እንዲጀምር ይፈቅዳል።ይህ ስልኩ ለመጀመር ረጅም ጊዜ እንዲፈጅ ሊያደርገው እና ትግበራው ሁልጊዜ በማሄድ ስልኩን በአጠቃላይ ለማዘግየት ይፈቅዳል።"</string>
<!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
<skip />
- <!-- outdated translation 1920045289234052219 --> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"ትግበራ ስርጭቱን ከጨረሰ በኋላ የሚቀር ተለጣፊ ስርጭት ለመላክ ይፈቅዳል።ተንኮል አዘል ትግበራዎች ስልኩን ማዘግየትወይም የተረጋጋ እንዳይሆን በማድረግ በጣም ብዙ ማህደረ ትውስታ እንዲጠቀም ማድረግ ይችላሉ።"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"ትግበራ ስርጭቱን ከጨረሰ በኋላ የሚቀር ተለጣፊ ስርጭት ለመላክ ይፈቅዳል።ተንኮል አዘል ትግበራዎች ጡባዊውን ማዘግየት ወይም የተረጋጋ እንዳይሆን በማድረግ በጣም ብዙ ማህደረ ትውስታ እንዲጠቀም ማድረግ ይችላሉ።"</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"ትግበራ ስርጭቱን ከጨረሰ በኋላ የሚቀር ተለጣፊ ስርጭት ለመላክ ይፈቅዳል።ተንኮል አዘል ትግበራዎች ስልኩን ማዘግየትወይም የተረጋጋ እንዳይሆን በማድረግ በጣም ብዙ ማህደረ ትውስታ እንዲጠቀም ማድረግ ይችላሉ።"</string>
<!-- no translation found for permlab_readContacts (6219652189510218240) -->
<skip />
- <!-- outdated translation 3371591512896545975 --> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"ትግበራ በስልክዎ ላይ የተከማቸውንዕውቂያ(አድራሻ) ሁሉ ውሂብ ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎንለሌላ ሰው ለመላክ ይህንመጠቀም ይችላሉ።"</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"ትግበራ በጡባዊዎ ላይ የተከማቸውንሁሉንም ዕውቂያ(አድራሻ) ውሂብ ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎንለሌላ ሰው ለመላክ ይህንመጠቀም ይችላሉ።"</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"ትግበራ በስልክዎ ላይ የተከማቸውንዕውቂያ(አድራሻ) ሁሉ ውሂብ ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎንለሌላ ሰው ለመላክ ይህንመጠቀም ይችላሉ።"</string>
<!-- no translation found for permlab_writeContacts (644616215860933284) -->
<skip />
- <!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"ትግበራ በስልክዎ ላይ የተከማቸውንዕውቂያ(አድራሻ) ሁሉ ውሂብ ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎን ለማጥፋት ወይም ለመቀየር ይህንመጠቀም ይችላሉ።"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"ትግበራ በጡባዊዎ ላይ የተከማቸውንዕውቂያ(አድራሻ) ውሂብ ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎን ለማጥፋት ወይም ለመቀየር ይህንመጠቀም ይችላሉ።"</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"ትግበራ በስልክዎ ላይ የተከማቸውንዕውቂያ(አድራሻ) ሁሉ ውሂብ ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች ውሂብዎን ለማጥፋት ወይም ለመቀየር ይህንመጠቀም ይችላሉ።"</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"የቀን መቁጠሪያ ክስተቶችን አንበብ"</string>
- <!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"ትግበራ በስልክዎ ላይ የተከማቹትን የቀን መቁጠሪያ ክስተቶች ሁሉ ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለሌላ ሰው ለመላክ ይህን መጠቀም ይችላሉ።"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"ትግበራ በጡባዊዎ ላይ የተከማቹትንሁሉ ንም የቀን መቁጠሪያ ክስተቶች ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለሌላ ሰው ለመላክ ይህን መጠቀም ይችላሉ።"</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"ትግበራ በስልክዎ ላይ የተከማቹትን የቀን መቁጠሪያ ክስተቶች ሁሉ ለማንበብ ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለሌላ ሰው ለመላክ ይህን መጠቀም ይችላሉ።"</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"አክል ወይም የቀን መቁጠሪያ ክስተቶችን ቀይር እና ለ እንግዶች ኢሜይል ላክ"</string>
<string name="permdesc_writeCalendar" msgid="2988871373544154221">"ትግበራ በቀን መቁጠሪያዎ ላይ ያለን ክስተት፣ ለተጋባዦች ኢሜይል ሊልክ ይችላል፣ ለማከል እና ለመለወጥ ይፈቅዳል። ተንኮል አዘል ትግበራዎች ይህን በመጠቀም የካላንደርዎን ክስተቶች ለማጥፋት ወይም ለመቀየር ይጠቀማሉ ወይም ለተጋባዦች ኢመይል ይልካሉ።"</string>
@@ -478,11 +486,11 @@
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"ለሙከራ ጊዜያዊ ሥፍራ ፍጠር። ተንኮል አዘል ትግበራዎች ሥፍራውን ለማገድ እና/ወይም በGPS ወይም የአውታረ መረብ አቅራቢዎች የእውነተኛውን ሥፍራ ሁኔታ ይዘው ከተመለሱ ወይም ስፍራዎን ተከታትለው ለውጪ ምንጭ ሪፖርት በማድረግ መጠቀም ይችላሉ።"</string>
<!-- no translation found for permlab_accessFineLocation (8116127007541369477) -->
<skip />
- <!-- outdated translation 7411213317434337331 --> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"በአለምአቀፍ አቀማመጥ ስርዓት ጥሩ ስፍራ ምንጮችን በስልክ ላይ፣ያለበት ቦታ ዽረስ። ተንኮል አዘል ትግበራዎች የትእንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ፣ እና ተጨማሪ የባትሪ ኃይል ሊፈጁ ይችላሉ።"</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"በአለምአቀፍ የመሬት አቀማመጥ ስርዓት(GPS) ጥሩ የሥፍራ ምንጮችን በጡባዊ ላይ፣ያለበት ሥፍራ፣ድረስ። ተንኮል አዘል ትግበራዎች የትእንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ፣ እና ተጨማሪ የባትሪ ኃይል ሊፈጁ ይችላሉ።"</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"በአለምአቀፍ አቀማመጥ ስርዓት ጥሩ ስፍራ ምንጮችን በስልክ ላይ፣ያለበት ቦታ ዽረስ። ተንኮል አዘል ትግበራዎች የትእንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ፣ እና ተጨማሪ የባትሪ ኃይል ሊፈጁ ይችላሉ።"</string>
<!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) -->
<skip />
- <!-- outdated translation 8235655958070862293 --> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"የተጠጋጋ የስልክ ሥፍራ አውታረ መረብ የውሂብ ጎታ ማወቅ የተለመዱ ሥፍራ ምንጮች፣ ያሉበት ቦታ ድረስ።ተንኮል አዘል ትግበራዎች የት አቅራቢያ እንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ።"</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"የጡባዊውን ቅርብ ሥፍራለማወቅ እንደጡባዊ አውታረ መረብ ውሂብ ጎታ ምንጮች፣ ያሉበት ሥፍራ፣ድረስ።ተንኮል አዘል ትግበራዎች የት አቅራቢያ እንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ።"</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"የተጠጋጋ የስልክ ሥፍራ አውታረ መረብ የውሂብ ጎታ ማወቅ የተለመዱ ሥፍራ ምንጮች፣ ያሉበት ቦታ ድረስ።ተንኮል አዘል ትግበራዎች የት አቅራቢያ እንዳሉ ለማወቅ ይህን መጠቀም ይችላሉ።"</string>
<!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) -->
<skip />
@@ -498,33 +506,29 @@
<string name="permdesc_recordAudio" msgid="6493228261176552356">"ትግበራ የድምፅ መዝገብ ዱካን ለመድረስ ይፈቅዳል።"</string>
<string name="permlab_camera" msgid="3616391919559751192">"ፎቶዎች እና ቪዲዮዎች አንሳ"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"ትግበራ በካሜራ ቪዲዮዎችን እና ምስሎችን ለመውሰድ ይፈቅዳል። ይህ ካሜራውን የሚታየውን ምስል በማንኛውም ጊዜ ለመሰብሰብ ይፈቅዳል።"</string>
- <!-- no translation found for permlab_brick (2961292205764488304) -->
- <skip />
- <!-- no translation found for permlab_brick (8337817093326370537) -->
- <skip />
- <!-- outdated translation 5569526552607599221 --> <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"ትግበራው ስልኩን በቋሚነት አለማስቻል ይፈቅዳል። ይህ በጣም አደገኛ ነው።"</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"በቋሚነት ጡባዊ አቦዝን"</string>
+ <!-- outdated translation 2961292205764488304 --> <string name="permlab_brick" product="default" msgid="8337817093326370537">"በቋሚነት ጡባዊ አቦዝን"</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"ትግበራው ጡባዊውን በቋሚነት ማቦዘን ይፈቅዳል። ይህ በጣም አደገኛ ነው።"</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"ትግበራው ስልኩን በቋሚነት አለማስቻል ይፈቅዳል። ይህ በጣም አደገኛ ነው።"</string>
- <!-- no translation found for permlab_reboot (3436634972561795002) -->
- <skip />
- <!-- no translation found for permlab_reboot (2898560872462638242) -->
- <skip />
- <!-- outdated translation 7914933292815491782 --> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"ትግበራ ስልኩ በዳግም አስነሳ ለማስገደድ ይፈቅዳል።"</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"ጡባዊ ዳግም እንዲነሳ አስገድድ"</string>
+ <!-- outdated translation 3436634972561795002 --> <string name="permlab_reboot" product="default" msgid="2898560872462638242">"ጡባዊ ዳግም እንዲነሳ አስገድድ"</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"ትግበራ ጡባዊውን በዳግም አስነሳ ለማስገደድ ይፈቅዳል።"</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"ትግበራ ስልኩ በዳግም አስነሳ ለማስገደድ ይፈቅዳል።"</string>
<!-- no translation found for permlab_mount_unmount_filesystems (1761023272170956541) -->
<skip />
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"ትግበራ መወገድ ለሚችል ማከማቻ ስርዓተ ፋይል ለመሰካት እና ለመንቀል ይፈቅዳል።"</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"ውጫዊ ማከማቻ ቅረፅ"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"ትግበራ መወገድ የሚችል ማከማቻ ለመቅረጽ ይፈቅዳል።"</string>
- <!-- outdated translation 1070364079249834666 --> <string name="permlab_asec_access" msgid="3411338632002193846">"በጥብቅ ማከማቻ ላይ መረጃ አግኝ"</string>
- <!-- outdated translation 7691616292170590244 --> <string name="permdesc_asec_access" msgid="8820326551687285439">"ትግበራ በጥብቅ ማከማቻ ላይ መረጃ ለማግኘት ይፈቅዳል።"</string>
- <!-- outdated translation 7312078032326928899 --> <string name="permlab_asec_create" msgid="6414757234789336327">"ጥብቅ ማከማቻ ፍጠር"</string>
- <!-- outdated translation 7041802322759014035 --> <string name="permdesc_asec_create" msgid="2621346764995731250">"ትግበራ ጥብቅ ማከማቻ ለመፍጠር ይፈቅዳል።"</string>
- <!-- outdated translation 7787322878955261006 --> <string name="permlab_asec_destroy" msgid="526928328301618022">"ጥብቅ ማከማቻ አጥፋ"</string>
- <!-- outdated translation 5740754114967893169 --> <string name="permdesc_asec_destroy" msgid="2746706889208066256">"ትግበራ ጥብቅ ማከማቻ ለመደምስስ ይፈቅዳል።"</string>
- <!-- outdated translation 7517449694667828592 --> <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"ጥብቅ ማከማቻ ሰካ/ንቀል"</string>
- <!-- outdated translation 5438078121718738625 --> <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"ትግበራ ጥብቅ ማከማቻ ለመሰካት/ለመንቀል ይፈቅዳል።"</string>
- <!-- outdated translation 5685344390439934495 --> <string name="permlab_asec_rename" msgid="7496633954080472417">"ጥብቅ ማከማቻ ድጋሚ ሰይም"</string>
- <!-- outdated translation 1387881770708872470 --> <string name="permdesc_asec_rename" msgid="2152829985238876790">"ትግበራ ጥብቅ ማከማቻ ድጋሚ ለመሰየም ይፈቅዳል።"</string>
+ <string name="permlab_asec_access" msgid="3411338632002193846">"በውስጥ ማከማቻ ላይ መረጃ አግኝ"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">" ትግበራ በውስጥ ማከማቻ መረጃ ለማግኘት ይፈቅዳል።"</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"የውስጥ ማከማቻ ፍጠር"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">" ትግበራ የውስጥ ማከማቻ ለመፍጠር ይፈቅዳል።"</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"የውስጥ ማከማቻ አጥፋ"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">" ትግበራ የውስጥ ማከማቻ ለማጥፋት ይፈቅዳል።"</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"የውስጥ ማከማቻ ሰካ/ንቀል"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">" ትግበራ በውስጥ ማከማቻ ለመሰካት/ለመንቀል ይፈቅዳል።"</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"የውስጥ ማከማቻ ድጋሚ ሰይም"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"ትግበራ የውስጥ ማከማቻ ዳግም ለመሰየም ይፈቅዳል።"</string>
<!-- no translation found for permlab_vibrate (7768356019980849603) -->
<skip />
<string name="permdesc_vibrate" msgid="2886677177257789187">"ትግበራ ነዛሪውንለመቆጣጠር ይፈቅዳል።"</string>
@@ -535,10 +539,8 @@
<skip />
<!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
<skip />
- <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
- <skip />
- <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
- <skip />
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"MTP ፕሮቶኮል ተግብር"</string>
+ <string name="permdesc_accessMtp" msgid="6532961200486791570">"መድረስ የMTP USB ፕሮቶኮልንወደ ከርነልMTP አንቀሳቃሽ ለመተግበር ይፈቅዳል።"</string>
<!-- no translation found for permlab_hardware_test (4148290860400659146) -->
<skip />
<string name="permdesc_hardware_test" msgid="3668894686500081699">"ትግበራው ለተለያዩ ፔሪፈራልስ ሃርድዌር ሙከራ ለመቆጣጠር ኣላማ ይፈቅዳል።"</string>
@@ -548,7 +550,7 @@
<!-- no translation found for permlab_callPrivileged (4198349211108497879) -->
<skip />
<string name="permdesc_callPrivileged" msgid="244405067160028452">"ያለእርስዎ ጣልቃ ገብነት የአደጋጊዜ ቁጥሮችን ጨምሮ፣ ትግበራው ወደ ማንኛውም ቁጥር ለመደወልይፈቅዳል።ተንኮል አዘል ትግበራዎች አላስፈላጊ እና ህገወጥ ጥሪዎችን ወደ አደጋ ጊዜ አገልግሎቶች ያደርጋሉ።"</string>
- <!-- outdated translation 5604848095315421425 --> <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"የCDMA ስልክ ጫን በቀጥታ አስጀምር"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"በቀጥታየCDMA ጡባዊ መዋቅር አስጀምር"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"የCDMA ስልክ ጫን በቀጥታ አስጀምር"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"ትግበራው የCDMA ፕሮቪዥን ለመጀመር ይፈቅዳል ። ተንኮል አዘል ትግበራዎች አላስፈላጊ የCDMA ፕሮቪዥን ይጀምራሉ።"</string>
<!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
@@ -564,21 +566,17 @@
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"ትግበራው የመሣሪያውን ስልክ ባህሪይ ለመቆጣጠር ይፈቅዳል። ይህ ፈቃድ ያለው ትግበራአውታረ መረቦችን ፣ ሬዲዮኖችን ማብራት ማጥፋት እና የመሳሰሉትን ለእርስዎ እንኳን ሳያሳውቅለመቀያየር ይችላል።"</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"የስልክ ሁኔታ እና መገለጫ አንብብ"</string>
<string name="permdesc_readPhoneState" msgid="188877305147626781">"ትግበራው የመሣሪያውን ስልክ ባህሪይ ለድረስ ይፈቅዳል። ይህ ፈቃድ ያለው ትግበራ ስልክ ቁጥሩን እና የዚህን ስልክ መለያ ቁጥር ፣ ጥሪው ገባሪ መሆን አለመሆኑን፣የተደወለበት ቁጥር የተያያዘ ወይም ያልተያያዘ እና የመሳሰሉት መሆኑን ለመወሰንይችላል።"</string>
- <!-- no translation found for permlab_wakeLock (1531731435011495015) -->
- <skip />
- <!-- no translation found for permlab_wakeLock (573480187941496130) -->
- <skip />
- <!-- outdated translation 7584036471227467099 --> <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"ትግበራ ስልኩን ከመተኛት መከልከል ይፈቅዳል።"</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ጡባዊ ከማንቀላፋት ተከላከል"</string>
+ <!-- outdated translation 1531731435011495015 --> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ጡባዊ ከማንቀላፋት ተከላከል"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"ትግበራ ጡባዊውን ከመተኛት መከልከል ይፈቅዳል።"</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"ትግበራ ስልኩን ከመተኛት መከልከል ይፈቅዳል።"</string>
- <!-- no translation found for permlab_devicePower (2787034722616350417) -->
- <skip />
- <!-- no translation found for permlab_devicePower (4928622470980943206) -->
- <skip />
- <!-- outdated translation 4577331933252444818 --> <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"ትግበራ ስልኩን ለማብራት እና ለማጥፋት ይፈቅዳል።"</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"ጡባዊ አብራ ወይም አጥፋ"</string>
+ <!-- outdated translation 2787034722616350417 --> <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"ጡባዊ አብራ ወይም አጥፋ"</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"ትግበራ ጡባዊውን ለማብራት እና ለማጥፋት ይፈቅዳል።"</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"ትግበራ ስልኩን ለማብራት እና ለማጥፋት ይፈቅዳል።"</string>
<!-- no translation found for permlab_factoryTest (3715225492696416187) -->
<skip />
- <!-- outdated translation 8136644990319244802 --> <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"ለስልኩ ሀርድዌር ሙሉመድረስበመፍቀድእንደ ዝቅተኛ-ደረጃ አምራች ሙከራ አሂድ። የሚገኘው ስልኩ በአምራች ሙከራ ሁነታ ላይ ሲአሄድ ብቻ ነው።"</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"ለመሣሪያው ሀርድዌር ሙሉ ድረስበመፍቀድ እንደ ዝቅተኛ-ደረጃ አምራች ሙከራ አሂድ። የሚገኘው መሣሪያው በአምራች ሙከራ ሁነታ ላይ ሲአሄድ ብቻ ነው።"</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"ለስልኩ ሀርድዌር ሙሉመድረስበመፍቀድእንደ ዝቅተኛ-ደረጃ አምራች ሙከራ አሂድ። የሚገኘው ስልኩ በአምራች ሙከራ ሁነታ ላይ ሲአሄድ ብቻ ነው።"</string>
<!-- no translation found for permlab_setWallpaper (6627192333373465143) -->
<skip />
@@ -590,17 +588,17 @@
<skip />
<string name="permdesc_masterClear" msgid="5033465107545174514">"ትግበራ ስርዓቱንሙሉ ለሙሉ ወደ ፋብሪካ ቅንብሮች ፣ ሁሉንም ውሂቦች ማጥፋት፣ማዋቀር፣ እና የተጫኑ ትግበራዎችን ድጋሚ ማስጀመር ይፈቅዳል።"</string>
<string name="permlab_setTime" msgid="2021614829591775646">"ሰዓት ሙላ"</string>
- <!-- outdated translation 667294309287080045 --> <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"ትግበራ የስልኩን ሰዓት ለመለወጥ ይፈቅዳል።"</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"ትግበራ የጡባዊን ሰዓት ለመለወጥ ይፈቅዳል።"</string>
<string name="permdesc_setTime" product="default" msgid="667294309287080045">"ትግበራ የስልኩን ሰዓት ለመለወጥ ይፈቅዳል።"</string>
<!-- no translation found for permlab_setTimeZone (2945079801013077340) -->
<skip />
- <!-- outdated translation 1902540227418179364 --> <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"የስልኩን ሰዓት ሰቅ ለመለወጥ ትግበራ ይፈቅዳል።"</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">" ትግበራየጡባዊን ሰዓት ሰቅ ለመለወጥ ይፈቅዳል።"</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"የስልኩን ሰዓት ሰቅ ለመለወጥ ትግበራ ይፈቅዳል።"</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"እንደ አውርድአዸራጅአገልግሎት"</string>
<string name="permdesc_accountManagerService" msgid="6056903274106394752">"ወደመለያ አረጋጋጮች ጥሪለማድረግ ትግበራ ይፈቅዳል"</string>
<!-- no translation found for permlab_getAccounts (4549918644233460103) -->
<skip />
- <!-- outdated translation 6839262446413155394 --> <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"ትግበራ በስልክ የሚታወቁ ዝርዝር መለያዎች ለማግኘት ይፈቅዳል።"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"ትግበራ በጡባዊ የሚታወቁ ዝርዝር መለያዎች ለማግኘት ይፈቅዳል።"</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"ትግበራ በስልክ የሚታወቁ ዝርዝር መለያዎች ለማግኘት ይፈቅዳል።"</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"እንደ መለያ አረጋጋጭ"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"ትግበራ የመለያ አረጋጋጭ መለያ አደራጅ ችሎታን ለመጠቀም፣ መለያ መፍጠር እናየይለፍ ቃሎችን ለማግኘት እና ለማቀናጀት አክሎ ይፈቅዳል።"</string>
@@ -634,19 +632,17 @@
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"ትግበራ ወደ እርስዎ መሣሪያ በቀጥታ ያልተመለከቱ ፓኬቶችን ለመቀበል ይፈቅዳል።ይህ አቅራቢያዎ የሚቀርቡ አገልገሎቶች ሲገኙ ጠቃሚ መሆን ይችላል።ብዙስምሪት ካልሆነሁነታ የበለጠ ተጨማሪ ኃይል ይጠቀማል።"</string>
<!-- no translation found for permlab_bluetoothAdmin (1092209628459341292) -->
<skip />
- <!-- outdated translation 7256289774667054555 --> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"የአካባቢውን ብሉቱዝ ስልክ ለማዋቀር እናአግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ትግበራ ይፈቅዳል።"</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"ትግበራየአካባቢውን ብሉቱዝ ጡባዊ ለማዋቀር እናአግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ይፈቅዳል።"</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"የአካባቢውን ብሉቱዝ ስልክ ለማዋቀር እናአግኝቶ ከሩቅ መሣሪያዎች ጋር ለማጣመር ትግበራ ይፈቅዳል።"</string>
<!-- no translation found for permlab_bluetooth (8361038707857018732) -->
<skip />
- <!-- outdated translation 762515380679392945 --> <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"ትግበራ የአካባቢውን ብሉቱዝ ስልክ ውቅር ለማየት፣ እና ከተጣመረው መሣሪያ ጋር ትይይዝ ለመቀበል እና ለማድረግ ይፈቅዳል።"</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"ትግበራ የአካባቢውን ብሉቱዝጡባዊ ውቅር ለማየት፣ እና ከተጣመረው መሣሪያ ጋር ትይይዝ ለማድረግ እና ለመቀበልይፈቅዳል።"</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"ትግበራ የአካባቢውን ብሉቱዝ ስልክ ውቅር ለማየት፣ እና ከተጣመረው መሣሪያ ጋር ትይይዝ ለመቀበል እና ለማድረግ ይፈቅዳል።"</string>
- <!-- no translation found for permlab_nfc (4423351274757876953) -->
- <skip />
- <!-- no translation found for permdesc_nfc (9171401851954407226) -->
- <skip />
+ <string name="permlab_nfc" msgid="4423351274757876953">"ቅርብ የግኑኙነትመስክ (NFC) ተቆጣጠር"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"ትግበራ የቅርብ ግኑኙነትመስክ (NFC) መለያዎች፣ ካርዶች እና አንባቢ ጋር ለማገናኘትይፈቅዳል።"</string>
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<!-- no translation found for permlab_disableKeyguard (4977406164311535092) -->
<skip />
@@ -671,41 +667,45 @@
<string name="permdesc_readDictionary" msgid="1082972603576360690">"ትግበራተጠቃሚው በተጠቃሚ መዝገበ ቃላት ሊያከማች የቻለውን ማንኛውም የግል ቃላት፣ስሞች፣እና ሀረጎች ለማንበብ ይፈቅዳል።"</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"በተጠቃሚ ፍቺ የተሰጠው መዝገበቃላት ፃፍ"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"ትግበራ በተጠቃሚ መዝገበ ቃላት ውስጥ አዲስ ቃል ለመፃፍ ይፈቅዳል።"</string>
- <!-- outdated translation 8079403759001777291 --> <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"የSD ካርድ ይዘትንቀይር/ሰርዝ"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"የUSB ማከማቻ ይዘቶችን ቀይር/ሰርዝ"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"የSD ካርድ ይዘትንቀይር/ሰርዝ"</string>
- <!-- outdated translation 6643963204976471878 --> <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"ትግበራ ወደ SD ካርድ ለመፃፍ ይፈቅዳል።"</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"ትግበራ ወደUSB ካርድ ለመፃፍ ይፈቅዳል።"</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"ትግበራ ወደ SD ካርድ ለመፃፍ ይፈቅዳል።"</string>
- <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
- <skip />
- <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
- <skip />
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"የውስጥ ማህደረ መረጃ ማከማቻ ይዘቶችን ቀይር/ሰርዝ"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"ትግበራ የውስጥ ማህደረ መረጃ ማከማቻ ይዘትን ለመቀየር ይፈቅዳል።"</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"የመሸጎጫ ስርዓተ ፋይል ድረስ"</string>
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"ትግበራ የመሸጎጫ ስርዓተፋይል ለማንበብ እና ለመፃፍ ይፈቅዳል።"</string>
- <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+ <string name="permlab_use_sip" msgid="5986952362795870502">"የበይነ መረብ ጥሪዎች አድርግ/ተቀበል"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">" ትግበራ ለ ግልጋሎት ለ የበይነ መረብ ጥሪዎች አድርግ/ተቀበል።"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
<skip />
- <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
<skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ድንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
- <!-- outdated translation 7227578260165172673 --> <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"ማያው ሲከፈት የገባውን የተሳሳተ የይለፍ ቃሎች ተቆጣጠር፣ እና ስልኩን ቆልፍ ወይም ብዙ የተሳሳቱ የይለፍ ቃሎች ከገቡ የስልኩን ውሂብ ሁሉ ደምስስ።"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"ማያው ሲከፈት የገቡ የተሳሳቱ የይለፍ ቃሎችን ብዛት ተቆጣጠር፣ እና ጡባዊውን ሸንጉርወይም በጣም ብዙ የተሳሳቱ የይለፍ ቃላት ከገቡ የጡባዊውን ውሂብ ሁሉ አጥፋ።"</string>
<string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"ማያው ሲከፈት የገባውን የተሳሳተ የይለፍ ቃሎች ተቆጣጠር፣ እና ስልኩን ቆልፍ ወይም ብዙ የተሳሳቱ የይለፍ ቃሎች ከገቡ የስልኩን ውሂብ ሁሉ ደምስስ።"</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"የማያ-መክፈቻ ይለፍ ቃል ለውጥ"</string>
<string name="policydesc_resetPassword" msgid="5391240616981297361">"የማያ-መክፈቻ ይለፍ ቃል ለውጥ"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"ማያ ቆልፍ"</string>
<string name="policydesc_forceLock" msgid="5696964126226028442">"ማያው እንዴት እና መቼ እንደሚቆልፍ ተቆጣጠር"</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"ሁሉንም ውሂብ ሰርዝ"</string>
- <!-- outdated translation 7669895333814222586 --> <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"የፋብሪካ ውሂብ ድጋሚ አስጀምር በማከናወን ያለ ማሰጠንቀቂያ የስልኩን ውሂብ ደምስስ።"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"የፋብሪካ ድጋሚ አስጀመርን በማከናወን፣ያለ ማስጠንቀቂያ የጡባዊውን ውሂብ አጥፋ"</string>
<string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"የፋብሪካ ውሂብ ድጋሚ አስጀምር በማከናወን ያለ ማሰጠንቀቂያ የስልኩን ውሂብ ደምስስ።"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"የመሣሪያውን ሁሉንም ፕሮክሲ አዘጋጅ"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ፖሊሲ እስኪነቃ ድረስ ለመጠቀም የመሣሪያውን ሁሉንም ፕሮክሲ አዘጋጅ። የመጀመሪያው የመሣሪያ አስተዳደር ብቻ የሁሉንም ፕሮክሲ ያዘጋጃል።"</string>
- <!-- no translation found for policylab_expirePassword (885279151847254056) -->
+ <!-- outdated translation 2314569545488269564 --> <string name="policylab_expirePassword" msgid="885279151847254056">"የይለፍ ቃል ጊዜ ማለፊያአዘጋጅ"</string>
+ <!-- outdated translation 7276906351852798814 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"የማያቆልፍ ይለፍ ቃል ለመለወጥ ምንያ ህል ጊዜእስደሚያስፈልገው ተቆጣጠር"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ማከማቻ ማመስጠር አዘጋጅ"</string>
+ <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"የተከማቸ ትግበራ ውሂብ መመስጠሩን ጠይቅ"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
- <!-- no translation found for policydesc_expirePassword (4844430354224822074) -->
- <skip />
- <!-- no translation found for policylab_encryptedStorage (8901326199909132915) -->
- <skip />
- <!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
<skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"መነሻ"</item>
@@ -771,11 +771,10 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"የስራ ምልክት ማድረጊያ"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"ረዳት"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <!-- no translation found for eventTypeCustom (7837586198458073404) -->
- <skip />
+ <string name="eventTypeCustom" msgid="7837586198458073404">"ብጁ"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"የልደት ቀን"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"ዓመታዊ በዓል"</string>
- <!-- outdated translation 5834288791948564594 --> <string name="eventTypeOther" msgid="7388178939010143077">"ዝግጅት"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"ሌላ"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"ብጁ"</string>
<string name="emailTypeHome" msgid="449227236140433919">"መነሻ"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"ስራ"</string>
@@ -802,41 +801,32 @@
<string name="orgTypeWork" msgid="29268870505363872">"ስራ"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"ሌላ"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"ብጁ"</string>
- <!-- no translation found for relationTypeCustom (3542403679827297300) -->
- <skip />
- <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
- <skip />
- <!-- no translation found for relationTypeBrother (8757913506784067713) -->
- <skip />
- <!-- no translation found for relationTypeChild (1890746277276881626) -->
- <skip />
- <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
- <skip />
- <!-- no translation found for relationTypeFather (5228034687082050725) -->
- <skip />
- <!-- no translation found for relationTypeFriend (7313106762483391262) -->
- <skip />
- <!-- no translation found for relationTypeManager (6365677861610137895) -->
- <skip />
- <!-- no translation found for relationTypeMother (4578571352962758304) -->
- <skip />
- <!-- no translation found for relationTypeParent (4755635567562925226) -->
- <skip />
- <!-- no translation found for relationTypePartner (7266490285120262781) -->
- <skip />
- <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
- <skip />
- <!-- no translation found for relationTypeRelative (1799819930085610271) -->
- <skip />
- <!-- no translation found for relationTypeSister (1735983554479076481) -->
- <skip />
- <!-- no translation found for relationTypeSpouse (394136939428698117) -->
- <skip />
+ <string name="relationTypeCustom" msgid="3542403679827297300">"ብጁ"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"ረዳት"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"ወንድም"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"ልጅ"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"የኑሮ አጋር"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"አባት"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"ጓደኛ"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"መናጅ"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"እናት"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"ወላጅ"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"አጋር"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"በ ተጠቅሷል"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"ዘመድ"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"እህት"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"የትዳር ጓደኛ"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"ብጁ"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"መነሻ"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"ስራ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"ሌላ"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN ኮድ አስገባ"</string>
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
+ <skip />
<!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
<skip />
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"ለመክፈት የይለፍ ቃል አስገባ"</string>
@@ -869,12 +859,14 @@
<skip />
<!-- no translation found for lockscreen_missing_sim_message_short (7381499217732227295) -->
<skip />
- <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
- <skip />
- <!-- no translation found for lockscreen_missing_sim_message (2186920585695169078) -->
- <skip />
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string>
+ <!-- outdated translation 151659196095791474 --> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string>
<!-- no translation found for lockscreen_missing_sim_instructions (8874620818937719067) -->
<skip />
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"የአደጋ ጊዜ ጥሪ ብቻ"</string>
<!-- no translation found for lockscreen_network_locked_message (143389224986028501) -->
<skip />
@@ -888,8 +880,7 @@
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">" የመክፈቻ ስርዓተ ጥለቱን <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="4906034376425175381">"የእርስዎን PIN<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="6827749231465145590">"የእርስዎን PIN <xliff:g id="NUMBER_0">%d</xliff:g> ጊዜ አሳስተው አስገብተዋል። "\n\n"እባክዎ በ <xliff:g id="NUMBER_1">%d</xliff:g> ሰከንድ እንደገና ይሞክሩ።"</string>
- <!-- no translation found for lockscreen_failed_attempts_almost_glogin (8687762517114904651) -->
- <skip />
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"የስርዓተጥለት መክፈቻዎን ተሳስተው <xliff:g id="NUMBER_0">%d</xliff:g>ጊዜዎች ስለዋል።ከ<xliff:g id="NUMBER_1">%d</xliff:g> ተጨማሪያልተሳካ ሙከራዎች በኋላ፣የGoogle ግባንበመጠቀም ጡባዊዎን እንዲከፍቱ ይጠየቃሉ።"\n\n"እባክዎ ከ <xliff:g id="NUMBER_2">%d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"የመክፈቻ ስርዓተ ጥለቱን<xliff:g id="NUMBER_0">%d</xliff:g>ጊዜ በስህተት ስለውታል።ከ<xliff:g id="NUMBER_1">%d</xliff:g> የበለጠ ያልተሳካ ሙከራ በኋላ፣ የGoogle መግቢያዎን ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።"\n\n"እባክዎ እንደገና ከ<xliff:g id="NUMBER_2">%d</xliff:g> ሰከንዶች በኋላ ይሞክሩ።"</string>
<!-- no translation found for lockscreen_too_many_failed_attempts_countdown (6251480343394389665) -->
<skip />
@@ -930,22 +921,16 @@
<!-- no translation found for save_password_label (6860261758665825069) -->
<skip />
<string name="double_tap_toast" msgid="1068216937244567247">"ጠቃሚ ምክር፡ለማጉላት እና ለማሳነስ ነካ ነካ አድርግ።"</string>
- <!-- no translation found for autofill_this_form (1272247532604569872) -->
- <skip />
- <!-- no translation found for setup_autofill (8154593408885654044) -->
- <skip />
- <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
- <skip />
- <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
- <skip />
- <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
- <skip />
- <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
- <skip />
+ <string name="autofill_this_form" msgid="1272247532604569872">"ራስ ሰር ሙላ"</string>
+ <string name="setup_autofill" msgid="8154593408885654044">"በራስሙላአዋቅር"</string>
+ <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">"፣ "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"የአሳሽ ታሪኮች እና ዕልባቶች አንብብ።"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ትግበራው ማሰሻው የጎበኛቸውን ሁሉ URL ኦች፣ እና የማሰሻውን ዕልባቶች ሁሉ ለማንበብ ይፈቅዳል።"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"የአሳሾች ታሪክ እና ዕልባቶች ፃፍ"</string>
- <!-- outdated translation 945571990357114950 --> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"ትግበራ በስልክዎ ላይ የተከማቹትንታሪኮች እና ዕልባቶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለማጥፋት ወይም ለመቀየር ይህን መጠቀም ይችላሉ።"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"ትግበራ በጡባዊዎ ላይ የተከማቹትንታሪኮች እና ዕልባቶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለማጥፋት ወይም ለመቀየር ይህን መጠቀም ይችላሉ።"</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"ትግበራ በስልክዎ ላይ የተከማቹትንታሪኮች እና ዕልባቶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለማጥፋት ወይም ለመቀየር ይህን መጠቀም ይችላሉ።"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"በማንቂያ ሰዓት ውስጥ ማንቂያ አዘጋጅ"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"ትግበራ በተጫነ የማንቂያ ሰዓት ትግበራ ማንቂያ ለማዘጋጀትይፈቅዳል። አንዳንድ የማንቂያ ሰዓት ትግበራዎች ይህን ገፅታ ላይተገብሩ ይችላሉ።"</string>
@@ -1096,8 +1081,7 @@
<skip />
<!-- no translation found for paste (5629880836805036433) -->
<skip />
- <!-- no translation found for pasteDisabled (7259254654641456570) -->
- <skip />
+ <string name="pasteDisabled" msgid="7259254654641456570">"ምንም የሚለጠፍ የለም"</string>
<!-- no translation found for copyUrl (2538211579596067402) -->
<skip />
<string name="selectTextMode" msgid="6738556348861347240">"ፅሁፍ ምረጥ"</string>
@@ -1106,10 +1090,8 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"የፅሁፍ እርምጃዎች"</string>
<!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
<skip />
- <!-- no translation found for low_internal_storage_view_text (4231085657068852042) -->
- <skip />
- <!-- no translation found for low_internal_storage_view_text (635106544616378836) -->
- <skip />
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"የጡባዊ ማከማቻ ቦታ እያነሰ ነው።"</string>
+ <!-- outdated translation 4231085657068852042 --> <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"የጡባዊ ማከማቻ ቦታ እያነሰ ነው።"</string>
<!-- no translation found for ok (5970060430562524910) -->
<skip />
<!-- no translation found for cancel (6442560571259935130) -->
@@ -1228,10 +1210,8 @@
<skip />
<!-- no translation found for sim_restart_button (4722407842815232347) -->
<skip />
- <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
- <skip />
- <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
- <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
<!-- no translation found for date_time_set (5777075614321087758) -->
<skip />
<!-- no translation found for default_permission_group (2690160991405646128) -->
@@ -1243,13 +1223,11 @@
<string name="usb_storage_activity_title" msgid="2399289999608900443">"USB ስብስብ ማከማቻ"</string>
<!-- no translation found for usb_storage_title (5901459041398751495) -->
<skip />
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"ስልክዎን ከኮምፒዩተርዎ ጋር በUSB አያይዘዋል። በኮምፒዩተርዎ እና በAndroid SD ካርድዎ መካከል ፋይሎች ለመገልበጥ ከፈለጉ ከታች ያለውን አዝራር ይምረጡ።"</string>
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="default" msgid="4510858346516069238">"ስልክዎን ከኮምፒዩተርዎ ጋር በUSB አያይዘዋል። በኮምፒዩተርዎ እና በAndroid SD ካርድዎ መካከል ፋይሎች ለመገልበጥ ከፈለጉ ከታች ያለውን አዝራር ይምረጡ።"</string>
+ <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"ኮምፒዩተርዎን በUSB በኩል አያይዘዋል።በኮምፒዩተርዎ እና በAndroid SD ማከማቻዎ መካከል ፋይሎች ለመቅዳት ከፈለጉከስርአዝራሩን ይንኩ።"</string>
+ <string name="usb_storage_message" product="default" msgid="4510858346516069238">"ኮምፒዩተርዎን በUSB በኩል አያይዘዋል።በኮምፒዩተርዎ እና በAndroid USB ማከማቻዎ መካከል ፋይሎች ለመቅዳት ከፈለጉከስርአዝራሩን ይንኩ።"</string>
<string name="usb_storage_button_mount" msgid="1052259930369508235">"የUSB ማከማቻ አብራ"</string>
- <!-- no translation found for usb_storage_error_message (3276413764430468454) -->
- <skip />
- <!-- no translation found for usb_storage_error_message (120810397713773275) -->
- <skip />
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"የUSB ማከማቻዎንለUSB ብዙማከማቻ መጠቀም ችግር አለ።"</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"የ SD ካርድዎንለUSB ብዙማከማቻ መጠቀም ችግር አለ።"</string>
<!-- no translation found for usb_storage_notification_title (8175892554757216525) -->
<skip />
<!-- no translation found for usb_storage_notification_message (7380082404288219341) -->
@@ -1257,7 +1235,7 @@
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"የUSB ማከማቻ አጥፋ"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"የUSB ማከማቻ ለማጥፋት ምረጥ።"</string>
<string name="usb_storage_stop_title" msgid="660129851708775853">"USB ማከማቻ በጥቅም ላይ"</string>
- <!-- outdated translation 3613713396426604104 --> <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"የUSB ማከማቻ ከመጥፋቱ በፊት፣ የAndroid SD ካርድዎ ከኮምፒዩተርዎ ላይ (“ወጥቷል”) መነቀልዎን ያረጋግጡ።"</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">" USB ማከማቻ ከማጥፋትዎ በፊት፣የ Android USB ማከማቸዎን ከኮምፒዩተርዎ መንቀልዎን(“ወጥቷል”) ያረጋግጡ።"</string>
<string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"የUSB ማከማቻ ከመጥፋቱ በፊት፣ የAndroid SD ካርድዎ ከኮምፒዩተርዎ ላይ (“ወጥቷል”) መነቀልዎን ያረጋግጡ።"</string>
<string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB ማከማቻ አጥፋ"</string>
<string name="usb_storage_stop_error_message" msgid="143881914840412108">"የ USB ማከማቻ ለማጥፋት ችግር ነበር። የ USB ጥገኛውን መንቀልዎን ለማረጋገጥ ይመልከቱ፣ ከዛም እንደገና ይሞክሩ።"</string>
@@ -1265,9 +1243,13 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"የUSB ማከማቻዎን ካበሩ፣ እየተጠቀሙባቸው ያሉ አንዳንድ ትግበራዎች ይቆማሉ እና የUSB ማከማቻ እስኪያጠፉ ድረስ ላይገኝ ይችላል።"</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB ክንውን አልተሳካም"</string>
<string name="dlg_ok" msgid="7376953167039865701">"እሺ"</string>
- <!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"የSD ካርድ ቅርፀት"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"የUSB ማከማቻ ቅረፅ"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"የSD ካርድ ቅርፀት"</string>
- <!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">" SD ካርዱን ለመቅረፅ በእርግጥይፈልጋሉ? በካርድዎ ላይ ያለ ውሂብ ሁሉ ይቋረጣል።"</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"የUSB ማከማቻ ቅረፅ፣እዚያ የተከማቹት ፋይሎች ሁሉ ይጥፉ? እርምጃውን መመለስ አይቻልም!"</string>
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">" SD ካርዱን ለመቅረፅ በእርግጥይፈልጋሉ? በካርድዎ ላይ ያለ ውሂብ ሁሉ ይቋረጣል።"</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"ቅርጸት"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"USB አድስ ተያይዟል"</string>
@@ -1278,28 +1260,28 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string>
- <!-- outdated translation 5457603418970994050 --> <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"SD ካርድ ማዘጋጀት"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB ማከማቻ በማዘጋጀት ላይ"</string>
<string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD ካርድ ማዘጋጀት"</string>
<string name="ext_media_checking_notification_message" msgid="8287319882926737053">"ስህተቶችን መመልከት።"</string>
- <!-- outdated translation 780477838241212997 --> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"ባዶ SD ካርድ"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"ባዶ የUSB ማከማቻ"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"ባዶ SD ካርድ"</string>
- <!-- outdated translation 3817704088027829380 --> <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD ካርድባዶ ነው ወይም የማይደገፍ ፋይል ስርዓት አለው።"</string>
+ <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB ማከማቻ ባዶ ነው ወይም የማይደገፍ ስርዓተ ፋይል አለው።"</string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD ካርድባዶ ነው ወይም የማይደገፍ ፋይል ስርዓት አለው።"</string>
- <!-- outdated translation 6410723906019100189 --> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"የወደመ SD ካርድ"</string>
+ <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"የተበላሸ የUSB ማከማቻ"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"የወደመ SD ካርድ"</string>
- <!-- outdated translation 6902531775948238989 --> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD ካርድ ወድሟል።ድጋሚ መቅረፅ ሊኖርብዎ ይችላል።"</string>
+ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB ማከማቻ ተበላሽቷል። ድጋሚ መቅረፅ ሊኖርብዎ ነው።"</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD ካርድ ወድሟል።ድጋሚ መቅረፅ ሊኖርብዎ ይችላል።"</string>
- <!-- outdated translation 6872152882604407837 --> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD ካርድ ሳይጠበቅ ተወግዷል"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB ማከማቻ በድንገት ተወግዷል"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD ካርድ ሳይጠበቅ ተወግዷል"</string>
- <!-- outdated translation 7260183293747448241 --> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"የውሂብ መጥፋትንከማስወደገድ በፊት የ SD ካርድ ንቀል።"</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"የውሂብ መጥፋት ለማስቀረትከመወገዱ በፊት የUSB ማከማቻ ንቀል"</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"የውሂብ መጥፋትንከማስወደገድ በፊት የ SD ካርድ ንቀል።"</string>
- <!-- outdated translation 6729801130790616200 --> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD ካርድበደህናለማውጣት"</string>
+ <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"የUSB ማከማቻ ለማስወገድ ደህና ነው"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD ካርድበደህናለማውጣት"</string>
- <!-- outdated translation 568841278138377604 --> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"SD ካርድ በደህናማስወገድ ይችላሉ።"</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"USB ማከማቻ በደህና ማስወገድ ይችላሉ።"</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"SD ካርድ በደህናማስወገድ ይችላሉ።"</string>
- <!-- outdated translation 8902518030404381318 --> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"የተወገደ SD ካርድ"</string>
+ <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB ማከማቻ ተወግዷል"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"የተወገደ SD ካርድ"</string>
- <!-- outdated translation 3870120652983659641 --> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD ካርድተወግዷል።አዲስ አስገባ።"</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB ማከማቻ ተወግዷል። አዲስ ማህደረ መረጃ አስገባ።"</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD ካርድተወግዷል።አዲስ አስገባ።"</string>
<string name="activity_list_empty" msgid="4168820609403385789">"ምንም ተመሳሳይ እንቅስቃሴዎች አልተገኙም"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"የስታስቲክስ አጠቃቀም ምንዝርን አዘምን"</string>
@@ -1313,8 +1295,7 @@
<string name="ime_action_send" msgid="2316166556349314424">" ይላኩ"</string>
<string name="ime_action_next" msgid="3138843904009813834">"በመቀጠል"</string>
<string name="ime_action_done" msgid="8971516117910934605">"ተከናውኗል"</string>
- <!-- no translation found for ime_action_previous (1443550039250105948) -->
- <skip />
+ <string name="ime_action_previous" msgid="1443550039250105948">"ያለፈው"</string>
<string name="ime_action_default" msgid="2840921885558045721">"አከናውን"</string>
<string name="dial_number_using" msgid="5789176425167573586">"የደወሉት ቁጥር"\n"<xliff:g id="NUMBER">%s</xliff:g> በመጠ ቀም ላይ"</string>
<string name="create_contact_using" msgid="4947405226788104538">\n"በመጠቀም <xliff:g id="NUMBER">%s</xliff:g> ዕውቂያ ፍጠር"</string>
@@ -1334,6 +1315,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"ንብርብር 2 ማስተላለፊያ ፕሮቶኮል"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"በቅድመ- አጋሪ ቁልፍL2TP/IPSec VPN የተመሰረተ"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"በL2TP/IPSec VPN ምስክርላይ የተመሰረተ"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"ፋይል ምረጥ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ምንም ፋይል አልተመረጠም"</string>
<string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
@@ -1355,60 +1344,33 @@
<item quantity="one" msgid="8167147081136579439">"1 ጨዋታ"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ከ <xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
- <!-- no translation found for action_mode_done (7217581640461922289) -->
- <skip />
- <!-- no translation found for progress_unmounting (535863554318797377) -->
- <skip />
- <!-- no translation found for progress_unmounting (5556813978958789471) -->
- <skip />
- <!-- no translation found for progress_erasing (4183664626203056915) -->
- <skip />
- <!-- no translation found for progress_erasing (2115214724367534095) -->
- <skip />
- <!-- no translation found for format_error (4320339096529911637) -->
- <skip />
- <!-- no translation found for format_error (1343380371925238343) -->
- <skip />
- <!-- no translation found for media_bad_removal (7960864061016603281) -->
- <skip />
- <!-- no translation found for media_checking (418188720009569693) -->
- <skip />
- <!-- no translation found for media_checking (7334762503904827481) -->
- <skip />
- <!-- no translation found for media_removed (7001526905057952097) -->
- <skip />
- <!-- no translation found for media_shared (5830814349250834225) -->
- <skip />
- <!-- no translation found for media_shared (5706130568133540435) -->
- <skip />
- <!-- no translation found for media_unknown_state (729192782197290385) -->
- <skip />
- <!-- no translation found for share (1778686618230011964) -->
- <skip />
- <!-- no translation found for find (4808270900322985960) -->
- <skip />
- <!-- no translation found for websearch (4337157977400211589) -->
- <skip />
- <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
- <skip />
- <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
- <skip />
- <!-- no translation found for gpsNotifMessage (1374718023224000702) -->
- <skip />
- <!-- no translation found for gpsVerifYes (2346566072867213563) -->
- <skip />
- <!-- no translation found for gpsVerifNo (1146564937346454865) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
- <skip />
- <!-- no translation found for sync_really_delete (8933566316059338692) -->
- <skip />
- <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
- <skip />
- <!-- no translation found for sync_do_nothing (8717589462945226869) -->
- <skip />
+ <string name="action_mode_done" msgid="7217581640461922289">"ተከናውኗል"</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"የUSB ማከማቻ በመንቀልላይ...."</string>
+ <string name="progress_unmounting" product="default" msgid="5556813978958789471">"የSD ካርድ በመ ንቀልላይ...."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB ማከማቻ በማጥፋት ላይ..."</string>
+ <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD ካርድ በማጥፋት ላይ..."</string>
+ <string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB ማከማቻ ለማጥፋት ተስኗል።"</string>
+ <string name="format_error" product="default" msgid="1343380371925238343">"SD ካርድ ለማጥፋት ተስኗል"</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"ከመነቀሉ በፊት SD ካርድ ተወግዶ ነበር።"</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB ማከማቻ በአሁኑ ጊዜ ታይቷል።"</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"SD ካርድ በአሁኑ ጊዜ ታይቷል።"</string>
+ <string name="media_removed" msgid="7001526905057952097">"SD ካርድ ተወግዷል።"</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB ማከማቻ በአሁኑ ጊዜ በኮምፒዩተርላይ በመገልገል ላይ ነው።"</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"SD ካርድ በአሁኑ ጊዜ በኮምፒዩተር ጥቅም ላይ ነው።"</string>
+ <string name="media_unknown_state" msgid="729192782197290385">"የውጭ ማህደረ ትውስታ በማይታወቅ ሁነታ ውስጥ።"</string>
+ <string name="share" msgid="1778686618230011964">"አጋራ"</string>
+ <string name="find" msgid="4808270900322985960">"አግኝ"</string>
+ <string name="websearch" msgid="4337157977400211589">"ድረ ፍለጋ"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"የስፍራ ጥየቃ ቅፅ<xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"የስፍራ ጥየቃ"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">" በ፡<xliff:g id="NAME">%1$s</xliff:g>(<xliff:g id="SERVICE">%2$s</xliff:g>) ተጠየቀ"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"አዎ"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"አይ"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"የሰርዝ ወሰን ከመጠን አልፏል"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"ለ<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g>፣መለያ <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>የተሰረዙ አይነቶችአሉ። ምን ማድረግ ይፈልጋሉ?"</string>
+ <string name="sync_really_delete" msgid="8933566316059338692">"አይነቶቹን ሰርዝ"</string>
+ <string name="sync_undo_deletes" msgid="8610996708225006328">"ስርዞቹን ቀልብስ።"</string>
+ <string name="sync_do_nothing" msgid="8717589462945226869">"ለአሁን ምንም አታድርግ።"</string>
<!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
<skip />
<!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
@@ -1435,4 +1397,16 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 8d5ecb8..648f665 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"كود PUK الذي أدخلته غير صحيح."</string>
<string name="mismatchPin" msgid="3695902225843339274">"أرقام التعريف الشخصية التي أدخلتها غير مطابقة."</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="ClipMmi" msgid="6952821216480289285">"معرف المتصل الوارد"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"وضع الطائرة"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"وضع الطائرة قيد التشغيل"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"وضع الطائرة متوقف"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"+100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
<string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"نظام Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"الخدمات التي تكلفك المال"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"للسماح للتطبيق بتلقي الرسائل القصيرة SMS ومعالجتها. قد تراقب بعض التطبيقات الضارة رسائلك أو تحذفها بدون عرضها لك."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"استلام رسالة وسائط متعددة (MMS)"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"للسماح للتطبيق بتلقي رسائل الوسائط المتعددة (MMS) ومعالجتها. قد تراقب بعض التطبيقات الضارة رسائلك أو تحذفها بدون عرضها لك."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"تلقي بث الطوارئ"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"للسماح للتطبيق بتلقي رسائل بث الطوارئ ومعالجتها. يتاح هذا الإذن لتطبيقات النظام فقط."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"إرسال رسائل قصيرة SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"للسماح للتطبيق بإرسال رسائل قصيرة SMS. قد تكلفك التطبيقات الضارة المال من خلال إرسال رسائل بدون تأكيدك."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"قراءة الرسائل القصيرة SMS أو رسائل الوسائط المتعددة"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"للسماح لتطبيق ما بفرض إغلاق أي نشاط في المقدمة والرجوع مرة أخرى. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_dump" msgid="1681799862438954752">"استرداد الحالة الداخلية للنظام"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"للسماح للتطبيق باسترداد الحالة الداخلية للنظام. قد تسترد التطبيقات الضارة مجموعة كبيرة من المعلومات الخاصة والآمنة التي لا حاجة لها في العادة على الإطلاق."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"استرداد محتوى الشاشة"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"للسماح للتطبيق باسترداد محتوى النافذة النشطة. ويمكن للتطبيقات الضارة استرداد محتوى النافذة بالكامل وفحص جميع النصوص بها باستثناء كلمات المرور."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"تغيير اتجاه الشاشة"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"للسماح لتطبيق ما بتغيير تدوير الشاشة في أي وقت. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغيير سرعة المؤشر"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"للسماح لتطبيق ما بتغيير سرعة مؤشر الماوس أو اللوحة اللمسية في أي وقت. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"إرسال إشارات Linux للتطبيقات"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"للسماح للتطبيق بطلب إرسال الإشارة المزوّدة لجميع العمليات المستمرة."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"تشغيل التطبيق دائمًا"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"كتابة بيانات جهة الاتصال"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"للسماح للتطبيق بتعديل بيانات جهة الاتصال (العنوان) المخزنة على الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة ذلك لمحو بيانات جهة الاتصال أو تعديلها."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"للسماح لتطبيق ما بتعديل بيانات (عنوان) جهة الاتصال المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات جهة الاتصال أو تعديلها."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"قراءة أحداث التقويم"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"للسماح لتطبيق ما بقراءة كل أحداث التقويم المخزنة على الجهاز اللوحي. ويمكن للتطبيقات الضارة استخدام ذلك لإرسال أحداث التقويم إلى أشخاص آخرين."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"للسماح لتطبيق ما بقراءة جميع أحداث التقويم المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال أحداث تقويمك إلى أشخاص آخرين."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"التحكم في اتصال الحقل القريب"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"للسماح لتطبيق ما بالاتصال بعلامات اتصال حقل قريب (NFC)، والبطاقات وبرامج القراءة."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"اعتراض وتعديل جميع حركات مرور البيانات عبر الشبكة"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"للسماح لتطبيق باعتراض وفحص جميع حركات مرور البيانات عبر الشبكة، على سبيل المثال، لإنشاء اتصال بالشبكة الظاهرية الخاصة VPN. قد تراقب التطبيقات الضارة حزم الشبكة أو تعيد توجيهها أو تعدلها بدون علمك."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"للسماح لتطبيق باعتراض وفحص جميع حركات مرور البيانات عبر الشبكة، لإنشاء اتصال بالشبكة الظاهرية الخاصة (VPN). قد تراقب التطبيقات الضارة حزم الشبكة أو تعيد توجيهها أو تعدلها بدون علمك."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"تعطيل تأمين المفاتيح"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"للسماح لتطبيق ما بتعطيل تأمين المفاتيح وأي أمان كلمة مرور مرتبطة. ومثال صحيح لذلك هو تعطيل الهاتف لتأمين المفاتيح عند استلام مكالمة هاتفية واردة، ثم إعادة تمكين تأمين المفاتيح عند انتهاء المكالمة."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"قراءة إعدادات المزامنة"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"للسماح لتطبيق ما بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"إجراء/تلقي مكالمات عبر الإنترنت"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"للسماح لتطبيق ما باستخدام خدمة SIP لإجراء/تلقي مكالمات عبر الإنترنت."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء قفل الشاشة"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"التحكم في عدد مرات تغيير كلمة مرور تأمين الشاشة"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"تعيين تشفير التخزين"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"طلب تشفير بيانات التطبيق المخزنة"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"الرئيسية"</item>
<item msgid="869923650527136615">"الجوال"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"العمل"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"غير ذلك"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"أدخل رقم التعريف الشخصي"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"أدخل رمز PUK ورقم التعريف الشخصي الجديد"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"رمز PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"رقم التعريف الشخصي الجديد"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"يمكنك اللمس لإدخال كلمة المرور"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"أدخل كلمة المرور لإلغاء التأمين"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"أدخل رقم التعريف الشخصي (PIN) لإلغاء القفل"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"الرجاء إدخال بطاقة SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"إذا شغّلت سعة تخزين USB، فستتوقف بعض التطبيقات التي تستخدمها وربما تصبح غير متاحة لحين إيقاف تشغيل سعة تخزين USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"أخفقت عملية USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"موافق"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"هل تريد تهيئة وحدة تخزين USB، ومحو كل الملفات المخزنة بها؟ لا يمكن عكس هذا الإجراء!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"بروتوكول الاتصال النفقي ثنائي الطبقة"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"بروتوكول L2TP/IPSec VPN المستند إلى المفتاح المشترك مسبقًا"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"بروتوكول L2TP/IPSec VPN المستند إلى الشهادة"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
<string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"وحدة التخزين الداخلية"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"بطاقة SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"وحدة تخزين USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"تعديل..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"شهادة الأمان"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"هذه الشهادة صالحة."</string>
+ <string name="issued_to" msgid="9032338008819841339">"تم الإصدار إلى:"</string>
+ <string name="common_name" msgid="5745530093500062357">"الاسم الشائع:"</string>
+ <string name="org_name" msgid="8868889052889991293">"المؤسسة:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"وحدة تنظيمية:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"تم الإصدار بواسطة:"</string>
+ <string name="validity_period" msgid="57988851973181309">"الصلاحية:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"تم الإصدار في:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"تنتهي الصلاحية في:"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b43b50f..6401b1c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Въведеният PUK е неправилен."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Въведените PIN кодове не съвпадат."</string>
<string name="invalidPin" msgid="3850018445187475377">"Въведете PIN с четири до осем цифри."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Въведете PUK код с поне осем цифри."</string>
<string name="needPuk" msgid="919668385956251611">"SIM картата ви е заключена с PUK. Въведете PUK кода, за да я отключите."</string>
<string name="needPuk2" msgid="4526033371987193070">"Въведете PUK2, за да отблокирате SIM картата."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Идентификация на вх. обаждания"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Самолетен режим"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Самолетният режим е ВКЛЮЧЕН"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Самолетният режим е ИЗКЛЮЧЕН"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Разрешава на приложението да получава и обработва SMS съобщения. Злонамерените приложения могат да наблюдават съобщенията ви или да ги изтрият, без да ви ги покажат."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"получаване на MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Разрешава на приложението да получава и обработва MMS съобщения. Злонамерените приложения могат да наблюдават съобщенията ви или да ги изтрият, без да ви ги покажат."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"получаване на спешни излъчвания"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Разрешава на приложението да получава и обработва спешни съобщения за излъчване. Това разрешение е налице само за системни приложения."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"изпращане на SMS съобщения"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Разрешава на приложението да изпраща SMS съобщения. Злонамерените приложения могат да ви въвлекат в разходи, като изпращат съобщения без потвърждение от ваша страна."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"четене на SMS или MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Разрешава на приложението принудително да затваря и да прехвърля на заден план всяка дейност, която е на преден план. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_dump" msgid="1681799862438954752">"извличане на вътрешното състояние на системата"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Разрешава на приложението да извлича вътрешното състояние на системата. Злонамерените приложения могат да извлекат разнообразна частна и защитена информация, която нормално не би трябвало да им е нужна."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"извличане на съдържанието на екрана"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Разрешава на приложението да извлича съдържанието от активния прозорец. Злонамерените приложения могат да извлекат цялото му съдържание и да проследят целия текст в него освен паролите."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Разрешава на притежателя да изпраща намерения до администратор на устройството. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"промяна на ориентацията на екрана"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Разрешава на приложението да променя ориентацията на екрана по всяко време. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"промяна на скоростта на курсор"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Разрешава на приложението да променя скоростта на курсора на мишката или на тракпада по всяко време. Обичайните приложения не би трябвало никога да се нуждаят от това."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"изпращане на сигнали от Linux до приложенията"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Разрешава на приложението да подаде заявка предоставеният сигнал да се изпрати до всички постоянни процеси."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"задаване на постоянно изпълнение на приложението"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"запис на данни за контактите"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в таблета ви. Злонамерените приложения може да използват това, за да изтрият или променят тези данни."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят тези данни."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"четене на събития от календара"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Разрешава на приложението да чете всички съхранени в таблета събития в календара ви. Злонамерените приложения могат да използват това, за да изпращат тези събития на други хора."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Разрешава на приложението да чете всички съхранени в телефона събития в календара ви. Злонамерените приложения могат да използват това, за да изпратят тези събития на други хора."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"контролиране на комуникацията в близкото поле"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Разрешава на приложението да комуникира с маркери, карти и четци, ползващи комуникация в близкото поле (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"прехващане и промяна на целия трафик от мрежата"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Разрешава на приложението да прехваща и проверява целия трафик от мрежата, например, за да установи връзка с VPN. Злонамерените приложения могат да наблюдават, пренасочват или променят пакети от мрежата без ваше знание."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Разрешава на приложението да прехваща и проверява целия трафик от мрежата, за да установи връзка с VPN. Злонамерените приложения могат да наблюдават, пренасочват или променят пакети от мрежата без ваше знание."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"деактивиране на заключването на клавиатурата"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Разрешава на приложението да деактивира заключването на клавиатурата и свързаната защита с парола. Това е допустимо, когато например телефонът деактивира заключването при получаване на входящо обаждане и после го активира отново, когато обаждането завърши."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"четене на настройките за синхронизиране"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешава на приложението да чете и записва във файловата система на кеша."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"извършване/получаване на интернет обаждания"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Разрешава на приложението да използва услугата SIP за извършване/получаване на интернет обаждания."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролирайте дължината и позволените знаци за паролите за отключване на екрана"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролирайте колко често трябва да се променя паролата за заключен екран"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Шифроване за хранилището"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Изисква съхраняваните данни за приложенията да бъдат шифровани"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Домашен"</item>
<item msgid="869923650527136615">"Мобилен"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Служебен"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Друг"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Въведете PIN кода"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Въведете PUK и новия ПИН код"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK код"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Нов ПИН код"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Докоснете и въведете парола"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Въведете паролата, за да отключите"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Въведете PIN за отключване"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"В таблета няма SIM карта."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"В телефона няма SIM карта."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Моля, поставете SIM карта."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако включите работата като USB устройство за съхранение, някои използвани от вас приложения ще спрат и може да бъдат недостъпни, докато не я изключите."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Операцията през USB не бе успешна"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Да се форматира ли USB хранилището, изтривайки всички файлове в него? Действието не може да бъде отменено!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Тунелен протокол за слой 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Основана на предварително споделен ключ L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Основана на сертификати L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
<string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Вътрешно хранилище"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD карта"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB хранилище"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Редактиране..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Сертификат за сигурност"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Сертификатът е валиден."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Издаден на:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Общо име:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Организация:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Организационна единица:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Издаден от:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Валидност:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Издаден на:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Изтича на:"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 2947b93..a2e75d3e 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"El PUK que heu escrit no és correcte."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Els PIN que heu introduït no coincideixen."</string>
<string name="invalidPin" msgid="3850018445187475377">"Escriviu un PIN que tingui de 4 a 8 números."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Introdueix un PUK compost com a mínim de 8 nombres."</string>
<string name="needPuk" msgid="919668385956251611">"La targeta SIM està bloquejada pel PUK. Escriviu el codi PUK per desbloquejar-la."</string>
<string name="needPuk2" msgid="4526033371987193070">"Escriviu el PUK2 per desbloquejar la targeta SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identificació de trucada entrant"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode d\'avió"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode d\'avió activat"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode d\'avió desactivat"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"+100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serveis de pagament"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permet a l\'aplicació rebre i processar missatges SMS. Les aplicacions malicioses poden supervisar els missatges o suprimir-los sense mostrar-vos-els."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"rebre MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permet a l\'aplicació rebre i processar missatges MMS. Les aplicacions malicioses poden supervisar els missatges o suprimir-los sense mostrar-vos-els."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"recepció d\'emissions d\'emergència"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permet que l\'aplicació rebi i processi missatges de difusió d\'emergència. Aquest permís només està disponible per a les aplicacions del sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar missatges SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permet a l\'aplicació enviar missatges SMS. Les aplicacions malicioses poden costar-vos diners en enviar missatges sense la vostra confirmació."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"llegir SMS o MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permet a una aplicació forçar una activitat en primer terme a tancar-se i tornar enrere. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_dump" msgid="1681799862438954752">"recuperar l\'estat intern del sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permet a una aplicació recuperar l\'estat intern del sistema. Les aplicacions malicioses poden recuperar molta informació variada de privadesa i seguretat que normalment no haurien de necessitar mai."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperació del contingut de la pantalla"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permet que l\'aplicació recuperi el contingut de la finestra activa. Les aplicacions malicioses poden recuperar el contingut de tota la finestra i examinar-ne tot el text, excepte les contrasenyes."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permet al titular enviar intencions a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"canviar l\'orientació de la pantalla"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permet a una aplicació canviar el gir de la pantalla en qualsevol moment. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"canvi de velocitat del punter"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permet que una aplicació canviï la velocitat del punter del ratolí o del ratolí tàctil en qualsevol moment. Mai no s\'hauria de necessitar per a les aplicacions normals."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"enviar senyals Linux a les aplicacions"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permet a l\'aplicació sol·licitar que el senyal subministrat s\'enviï a tots els processos persistents."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"fer que l\'aplicació s\'executi sempre"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"escriure dades de contacte"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet que una aplicació modifiqui les dades de contactes (adreces) emmagatzemades a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per esborrar o per modificar les teves dades de contactes."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet a una aplicació modificar les dades de contacte (adreça) emmagatzemades al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades de contacte."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"llegir els esdeveniments del calendari"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet que una aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per enviar els teus esdeveniments del calendari a altres persones."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet a una aplicació llegir tots els esdeveniments del calendari emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per enviar els vostres esdeveniments del calendari a altres persones."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controla Near Field Communication (NFC)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permet que una aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Near Field Communication (NFC)"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"intercepta i modifica tot el trànsit de la xarxa"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permet que una aplicació intercepti i inspeccioni tot el trànsit de la xarxa, per exemple, per establir una connexió VPN. Les aplicacions malintencionades poden controlar, redirigir o modificar paquets de xarxa sense el teu coneixement."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permet que una aplicació intercepti i inspeccioni tot el trànsit de la xarxa per establir una connexió VPN. Les aplicacions malintencionades poden controlar, redirigir o modificar paquets de xarxa sense el teu coneixement."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueig del teclat"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet a una aplicació desactivar el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Un exemple d\'això és la desactivació per part del telèfon del bloqueig del teclat en rebre una trucada telefònica entrant i després la reactivació del bloqueig del teclat quan finalitza la trucada."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet a una aplicació llegir el sistema de fitxers de la memòria cau i escriure-hi."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"fes/rep trucades per Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permet que una aplicació utilitzi el servei SIP per fer i rebre trucades per Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa els intents de desbloqueig de la pantalla"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Controla la freqüència amb què cal canviar la contrasenya de bloqueig de pantalla"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Casa"</item>
<item msgid="869923650527136615">"Mòbil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Feina"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altres"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduïu el codi PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Introdueix el codi PUK i el codi PIN nou"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codi PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Codi PIN nou"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Toca per introduir contrasenya"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduïu la contrasenya per desbloquejar-lo"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introdueix el PIN per desbloquejar"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hi ha cap targeta SIM al telèfon."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inseriu una targeta SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Només trucades d\'emergència"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Xarxa bloquejada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La targeta SIM està bloquejada pel PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activeu l\'emmagatzematge USB, algunes de les aplicacions que utilitzeu s\'aturaran i pot ser que no estiguin disponibles fins que desactiveu l\'emmagatzematge USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Error de l\'operació d\'USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formata l\'emmag. USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formata la targeta SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vols formatar l\'emmagatzematge USB i esborrar tots els fitxers que hi ha emmagatzemats? L\'acció no es podrà desfer."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol de tunelització de capa 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clau compartida prèviament"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificats"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
<string name="reset" msgid="2448168080964209908">"Reinicia"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Emmagatzematge intern"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Targeta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Emmagatzematge USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Edita..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de seguretat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Aquest certificat és vàlid."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emès per a:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nom comú:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organització:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unitat organitzativa:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Publicat per:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validesa:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Publicat el:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Caduca el:"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 92deaca..ca3035d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Kód PUK byl zadán nesprávně."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Zadané kódy PIN se neshodují."</string>
<string name="invalidPin" msgid="3850018445187475377">"Zadejte kód PIN o délce 4-8 číslic."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Zadejte osmimístný nebo delší kód PUK."</string>
<string name="needPuk" msgid="919668385956251611">"Karta SIM je blokována pomocí kódu PUK. Odblokujete ji zadáním kódu PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Chcete-li odblokovat kartu SIM, zadejte kód PUK2."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Příchozí identifikace volajícího"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V letadle"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V letadle je ZAPNUTÝ"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V letadle je VYPNUTÝ"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Zpoplatněné služby"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Umožňuje aplikaci přijímat a zpracovávat zprávy SMS. Škodlivé aplikace mohou sledovat vaše zprávy nebo je smazat, aniž by vám byly zobrazeny."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"příjem zpráv MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Umožňuje aplikaci přijímat a zpracovávat zprávy MMS. Škodlivé aplikace mohou sledovat vaše zprávy nebo je smazat, aniž by vám byly zobrazeny."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"příjem nouzového vysílání"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Umožňuje aplikaci přijímat a zpracovávat zprávy nouzového vysílání. Toto oprávnění je dostupné jen pro systémové aplikace."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"odesílaní zpráv SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Umožňuje aplikaci odesílat zprávy SMS. Škodlivé aplikace mohou bez vašeho potvrzení odesílat zpoplatněné zprávy."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"čtení zpráv SMS a MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Umožňuje aplikaci vynutit zavření a přesunutí libovolné činnosti v popředí na pozadí. Běžné aplikace by toto nastavení neměly nikdy využívat."</string>
<string name="permlab_dump" msgid="1681799862438954752">"načtení interního stavu systému"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Umožňuje aplikaci načíst interní stav systému. Škodlivé aplikace mohou načíst řádu soukromých a zabezpečených informací, které by nikdy neměly potřebovat."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načtení obsahu obrazovky"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Umožňuje aplikaci načíst obsah aktivního okna. Škodlivé aplikace mohou načíst celý obsah okna a prozkoumat veškerý text kromě hesel."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"částečné vypnutí"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Umožňuje držiteli oprávnění odesílat informace správci zařízení. Běžné aplikace by toto oprávnění nikdy neměly požadovat."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"změna orientace obrazovky"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Umožňuje aplikaci kdykoli změnit orientaci obrazovky. Běžné aplikace by toto nastavení nikdy neměly využívat."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"změna rychlosti kurzoru"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Umožňuje aplikaci kdykoli změnit rychlost kurzoru myši nebo trackpadu. U běžných aplikací by to nikdy nemělo být potřeba."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"odeslání signálů Linux aplikacím"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Umožňuje aplikaci vyžádat zaslání poskytnutého signálu všem trvalým procesům."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"trvalé spuštění aplikace"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"zápis dat kontaktů"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Umožňuje aplikaci změnit kontaktní údaje (adresu) uložené v tabletu. Škodlivé aplikace toto oprávnění mohou zneužít a vymazat či pozměnit kontaktní údaje."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Umožňuje aplikaci změnit kontaktní údaje (adresu) uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit kontaktní údaje."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"Čtení událostí v kalendáři"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Umožňuje aplikaci číst všechny události kalendáře uložené v tabletu. Škodlivé aplikace toho mohou zneužít a odeslat události z vašeho kalendáře jiným lidem."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Umožňuje aplikaci načíst všechny události kalendáře uložené ve vašem telefonu. Škodlivé aplikace poté mohou dalším lidem odeslat události z vašeho kalendáře."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"ovládat technologii NFC"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"zachytit a upravit veškerý síťový provoz"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Umožňuje aplikaci zastavit a kontrolovat veškerý síťový provoz, například za účelem navázání připojení VPN. Škodlivé aplikace mohou sledovat, přesměrovat nebo měnit síťové pakety bez vašeho vědomí."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Umožňuje aplikaci zachytit a kontrolovat veškerý síťový provoz za účelem navázání připojení VPN. Škodlivé aplikace mohou sledovat, přesměrovat nebo měnit síťové pakety bez vašeho vědomí."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"vypnutí zámku kláves"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Příkladem oprávněného použití této funkce je vypnutí zámku klávesnice při příchozím hovoru a jeho opětovné zapnutí po skončení hovoru."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"uskutečňovat a přijímat internetové hovory"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikaci uskutečnit a přijímat internetové hovory pomocí služby SIP."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Řídit délku hesel pro odemčení obrazovky a v nich používané znaky"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Určuje, jak často je třeba měnit heslo pro uzamčení obrazovky"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavit šifrování úložiště"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Požadovat šifrování ukládaných dat"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Domů"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Práce"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Jiné"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Zadejte kód PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Zadejte kód PUK a nový kód PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kód PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nový kód PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Dotknete-li se tohoto pole, budete moci zadat heslo"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Zadejte heslo pro odblokování"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Zadejte kód PIN pro odblokování"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabletu není karta SIM."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu není žádná karta SIM."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Prosím vložte kartu SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Pouze tísňová volání"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Síť je blokována"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM je zablokována pomocí kódu PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Pokud zapnete úložiště USB, dojde k zastavení některých používaných aplikací. Tyto aplikace pravděpodobně nebudou k dispozici až do vypnutí úložiště USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Chyba operace na rozhraní USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formátovat úložiště USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovat kartu SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete úložiště USB zformátovat a tím smazat všechny soubory, které v něm jsou uloženy? Tuto akci nelze vrátit zpět."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol L2TP (Layer 2 Tunneling Protocol)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Síť VPN L2TP/IPSec s předsdíleným klíčem"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Síť VPN L2TP/IPSec s certifikátem"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Není vybrán žádný soubor"</string>
<string name="reset" msgid="2448168080964209908">"Resetovat"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Interní úložiště"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Úložiště USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Upravit..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certifikát zabezpečení"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Tento certifikát je platný."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Vydáno komu:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Běžný název:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizace:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizační jednotka:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Vydal:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Platnost:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Datum vydání:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Platnost vyprší:"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a3149a2..7153416 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Den indtastede PUK-kode er ikke korrekt."</string>
<string name="mismatchPin" msgid="3695902225843339274">"De indtastede PIN-koder stemmer ikke overens."</string>
<string name="invalidPin" msgid="3850018445187475377">"Indtast en PIN-kode på mellem 4 og 8 tal."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Angiv en PUK-kode på 8 eller flere cifre."</string>
<string name="needPuk" msgid="919668385956251611">"Dit SIM-kort er låst med PUK-koden. Indtast PUK-koden for at låse den op."</string>
<string name="needPuk2" msgid="4526033371987193070">"Indtast PUK2-koden for at låse op for SIM-kortet."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Indgående opkalds-id"</string>
@@ -140,7 +141,7 @@
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon slukkes nu."</string>
<string name="shutdown_confirm_question" msgid="6656441286856415014">"Vil du slukke?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Seneste"</string>
- <string name="no_recent_tasks" msgid="279702952298056674">"Der er ingen nye programmer."</string>
+ <string name="no_recent_tasks" msgid="279702952298056674">"Der er ingen nye applikationer."</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Valgmuligheder for tabletcomputeren"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Indstillinger for telefon"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Skærmlås"</string>
@@ -151,11 +152,11 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flytilstand"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flytilstand er TIL"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flytilstand er slået FRA"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
- <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Tillader, at et program kan gøre ting, som kan koste penge."</string>
+ <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Tillader, at en applikation kan gøre ting, som kan koste penge."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string>
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Læs og skriv dine sms-, e-mail- og andre beskeder."</string>
<string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Dine personlige oplysninger"</string>
@@ -164,7 +165,7 @@
<string name="permgrouplab_location" msgid="635149742436692049">"Din placering"</string>
<string name="permgroupdesc_location" msgid="2430258821648348660">"Overvåg din fysiske placering"</string>
<string name="permgrouplab_network" msgid="5808983377727109831">"Netværkskommunikation"</string>
- <string name="permgroupdesc_network" msgid="5035763698958415998">"Tillader, at programmerne får adgang til forskellige netværksfunktioner."</string>
+ <string name="permgroupdesc_network" msgid="5035763698958415998">"Tillader, at applikationerne får adgang til forskellige netværksfunktioner."</string>
<string name="permgrouplab_accounts" msgid="3359646291125325519">"Dine konti"</string>
<string name="permgroupdesc_accounts" msgid="4948732641827091312">"Få adgang til de tilgængelige konti."</string>
<string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Hardwarekontroller"</string>
@@ -179,307 +180,325 @@
<string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Få adgang til USB-lager."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Få adgang til SD-kortet."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"deaktiver eller rediger statuslinje"</string>
- <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillader, at et program deaktiverer statuslinjen eller tilføjer eller fjerner systemikoner."</string>
+ <string name="permdesc_statusBar" msgid="1365473595331989732">"Tillader, at en applikation deaktiverer statuslinjen eller tilføjer eller fjerner systemikoner."</string>
<string name="permlab_statusBarService" msgid="7247281911387931485">"statusbjælke"</string>
- <string name="permdesc_statusBarService" msgid="4097605867643520920">"Tillader, at programmet er statusbjælken."</string>
+ <string name="permdesc_statusBarService" msgid="4097605867643520920">"Tillader, at applikationen er statusbjælken."</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"udvid/skjul statuslinje"</string>
- <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Tillader, at et program udvider eller skjuler statuslinjen."</string>
+ <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Tillader, at en applikation udvider eller skjuler statuslinjen."</string>
<string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"opfang udgående opkald"</string>
- <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Tillader, at et program behandler udgående opkald og ændrer det nummer, der ringes til. Ondsindede programmer kan overvåge, omdirigere eller forhindre udgående opkald."</string>
+ <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Tillader, at en applikation behandler udgående opkald og ændrer det nummer, der ringes til. Ondsindede applikationer kan overvåge, omdirigere eller forhindre udgående opkald."</string>
<string name="permlab_receiveSms" msgid="2697628268086208535">"modtag sms"</string>
- <string name="permdesc_receiveSms" msgid="6298292335965966117">"Tillader, at et program modtager og behandler sms-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
+ <string name="permdesc_receiveSms" msgid="6298292335965966117">"Tillader, at en applikation modtager og behandler sms-beskeder. Ondsindede applikationer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"modtag mms"</string>
- <string name="permdesc_receiveMms" msgid="4563346832000174373">"Tillader, at et program modtager og behandler mms-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
+ <string name="permdesc_receiveMms" msgid="4563346832000174373">"Tillader, at en applikation modtager og behandler mms-beskeder. Ondsindede applikationer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"modtage nødudsendelser"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Tillader, at en applikation kan modtage og behandle nødudsendelser. Denne tilladelse er kun tilgængelig for systemapplikationer."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"send sms-beskeder"</string>
- <string name="permdesc_sendSms" msgid="1946540351763502120">"Tillader, at et program at sender sms-beskeder. Ondsindede programmer kan eventuelt koste dig penge ved at sende beskeder uden din bekræftelse."</string>
+ <string name="permdesc_sendSms" msgid="1946540351763502120">"Tillader, at en applikation at sender sms-beskeder. Ondsindede applikationer kan eventuelt koste dig penge ved at sende beskeder uden din bekræftelse."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"læs sms eller mms"</string>
- <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Tillader, at et program læser sms-beskeder, der er gemt på din tabletcomputer eller dit SIM-kort. Ondsindede programmer kan eventuelt læse dine fortrolige beskeder."</string>
- <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Tillader, at et program læser sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede programmer kan eventuelt læse dine fortrolige beskeder."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Tillader, at en applikation læser sms-beskeder, der er gemt på din tabletcomputer eller dit SIM-kort. Ondsindede applikationer kan eventuelt læse dine fortrolige beskeder."</string>
+ <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Tillader, at en applikation læser sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede applikationer kan eventuelt læse dine fortrolige beskeder."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"rediger sms eller mms"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Tillader, at et program skriver i sms-beskeder, der er gemt på din tabletcomputer eller dit SIM-kort. Ondsindede programmer kan eventuelt slette dine beskeder."</string>
- <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Tillader, at et program skriver i sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede programmer kan eventuelt slette dine beskeder."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Tillader, at en applikation skriver i sms-beskeder, der er gemt på din tabletcomputer eller dit SIM-kort. Ondsindede applikationer kan eventuelt slette dine beskeder."</string>
+ <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Tillader, at en applikation skriver i sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede applikationer kan eventuelt slette dine beskeder."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"modtag WAP"</string>
- <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Tillader, at et program modtager og behandler WAP-beskeder. Ondsindede programmer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
- <string name="permlab_getTasks" msgid="5005277531132573353">"hent kørende programmer"</string>
- <string name="permdesc_getTasks" msgid="7048711358713443341">"Tillader, at et program henter oplysninger om nuværende og for nyligt kørende opgaver. Tillader, at eventuelt ondsindede programmer finder private oplysninger om andre programmer."</string>
- <string name="permlab_reorderTasks" msgid="5669588525059921549">"omorganiser kørende programmer"</string>
- <string name="permdesc_reorderTasks" msgid="126252774270522835">"Tillader, at et program flytter opgaver til forgrunden og baggrunden. Ondsindede programmer kan tvinge dem selv til forgrunden uden din kontrol."</string>
- <string name="permlab_removeTasks" msgid="4802740047161700683">"stop kørende programmer"</string>
- <string name="permdesc_removeTasks" msgid="2000332928514575461">"Tillader, at et program fjerner opgaver og standser deres programmer. Ondsindede programmer kan forstyrre andre programmers opførsel."</string>
+ <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Tillader, at en applikation modtager og behandler WAP-beskeder. Ondsindede applikationer kan overvåge dine beskeder eller slette dem uden at vise dem til dig."</string>
+ <string name="permlab_getTasks" msgid="5005277531132573353">"hent kørende applikationer"</string>
+ <string name="permdesc_getTasks" msgid="7048711358713443341">"Tillader, at en applikation henter oplysninger om nuværende og for nyligt kørende opgaver. Tillader, at eventuelt ondsindede applikationer finder private oplysninger om andre applikationer."</string>
+ <string name="permlab_reorderTasks" msgid="5669588525059921549">"omorganiser kørende applikationer"</string>
+ <string name="permdesc_reorderTasks" msgid="126252774270522835">"Tillader, at en applikation flytter opgaver til forgrunden og baggrunden. Ondsindede applikationer kan tvinge dem selv til forgrunden uden din kontrol."</string>
+ <string name="permlab_removeTasks" msgid="4802740047161700683">"stop kørende applikationer"</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"Tillader, at en applikation fjerner opgaver og standser deres applikationer. Ondsindede applikationer kan forstyrre andre applikationers opførsel."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"aktiver programfejlretning"</string>
- <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Tillader, at et program slår fejlretning af andet program til. Ondsindede programmer kan bruge dette til at standse andre programmer."</string>
+ <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Tillader, at en applikation slår fejlretning af en anden applikation til. Ondsindede applikationer kan bruge dette til at standse andre applikationer."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"skift indstillinger for brugergrænsefladen"</string>
- <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Tillader, at et program ændrer den nuværende konfiguration, f.eks. den lokale eller overordnede skrifttypestørrelse."</string>
+ <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Tillader, at en applikation ændrer den nuværende konfiguration, f.eks. den lokale eller overordnede skrifttypestørrelse."</string>
<string name="permlab_enableCarMode" msgid="5684504058192921098">"aktivere biltilstand"</string>
- <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Tillader et program at aktivere biltilstand."</string>
+ <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Tillader en applikation at aktivere biltilstand."</string>
<string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"standse baggrundsprocesser"</string>
- <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Tillader et program at standse andre programmers baggrundsprocesser, selvom der ikke er mangel på hukommelse."</string>
- <string name="permlab_forceStopPackages" msgid="1447830113260156236">"tvangsstandse andre programmer"</string>
- <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Tillader, at et program tvangsstopper andre programmer."</string>
- <string name="permlab_forceBack" msgid="1804196839880393631">"tving programmet til at lukke"</string>
- <string name="permdesc_forceBack" msgid="6534109744159919013">"Tillader, at et program tvinger alle programmer, der er i forgrunden, til at lukke og køre i baggrunden. Bør aldrig være nødvendigt til normale programmer."</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Tillader en applikation at standse andre programmers baggrundsprocesser, selvom der ikke er mangel på hukommelse."</string>
+ <string name="permlab_forceStopPackages" msgid="1447830113260156236">"tvangsstandse andre applikationer"</string>
+ <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Tillader, at en applikation tvangsstopper andre applikationer."</string>
+ <string name="permlab_forceBack" msgid="1804196839880393631">"tving applikationen til at lukke"</string>
+ <string name="permdesc_forceBack" msgid="6534109744159919013">"Tillader, at en applikation tvinger alle applikationer, der er i forgrunden, til at lukke og køre i baggrunden. Bør aldrig være nødvendigt til normale applikationer."</string>
<string name="permlab_dump" msgid="1681799862438954752">"hent intern systemtilstand"</string>
- <string name="permdesc_dump" msgid="2198776174276275220">"Tillader, at et program henter systemets interne tilstand. Ondsindede programmer kan hente en række private og sikre oplysninger, som de normalt aldrig bør have brug for."</string>
+ <string name="permdesc_dump" msgid="2198776174276275220">"Tillader, at en applikation henter systemets interne tilstand. Ondsindede applikationer kan hente en række private og sikre oplysninger, som de normalt aldrig bør have brug for."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hente skærmindhold"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Tillader, at en applikation kan hente indholdet i det aktive vindue. Ondsindede applikationer kan hente hele vinduets indhold og undersøge al tekst undtagen adgangskoder."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delvis lukning"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Sætter aktivitetsadministratoren i lukningstilstand. Lukker ikke helt ned."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
- <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Forhindrer brugeren i at skifte til et andet program."</string>
- <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"overvåg og kontroller start af alle programmer"</string>
- <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Tillader, at et program overvåger og kontrollerer, hvordan systemet starter aktiviteter. Ondsindede programmer kan fuldstændigt kompromittere systemet. Denne tilladelse er kun nødvendig til udvikling, aldrig til normal brug."</string>
+ <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Forhindrer brugeren i at skifte til en anden applikation."</string>
+ <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"overvåg og kontroller start af alle applikationer"</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Tillader, at en applikation overvåger og kontrollerer, hvordan systemet starter aktiviteter. Ondsindede applikationer kan fuldstændigt kompromittere systemet. Denne tilladelse er kun nødvendig til udvikling, aldrig til normal brug."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"send udsendelse om fjernet pakke"</string>
- <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Tillader, at et program udsender en meddelelse om, at en programpakke er fjernet. Ondsindede programmer kan bruge dette til at afslutte et andet kørende program."</string>
+ <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Tillader, at en applikation udsender en meddelelse om, at en applikationspakke er fjernet. Ondsindede applikationer kan bruge dette til at afslutte en anden kørende applikation."</string>
<string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"send sms-modtaget udsendelse"</string>
- <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Tillader, at et program udsender en meddelelse om, at der er modtaget en sms-besked. Ondsindede programmer kan eventuelt bruge dette til at forfalske indgående sms-beskeder."</string>
+ <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Tillader, at en applikation udsender en meddelelse om, at der er modtaget en sms-besked. Ondsindede applikationer kan eventuelt bruge dette til at forfalske indgående sms-beskeder."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-modtaget udsendelse"</string>
- <string name="permdesc_broadcastWapPush" msgid="3955303669461378091">"Tillader, at et program udsender en meddelelse om, at der er modtaget en WAP PUSH-besked. Ondsindede programmer kan eventuelt bruge dette til at forfalske modtagelse af mms-besked eller i det skjulte erstatte indholdet på alle websider med ondsindede varianter."</string>
+ <string name="permdesc_broadcastWapPush" msgid="3955303669461378091">"Tillader, at en applikation udsender en meddelelse om, at der er modtaget en WAP PUSH-besked. Ondsindede applikationer kan eventuelt bruge dette til at forfalske modtagelse af mms-besked eller i det skjulte erstatte indholdet på alle websider med ondsindede varianter."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"begræns antallet af kørende processer"</string>
- <string name="permdesc_setProcessLimit" msgid="7824786028557379539">"Tillader, at et program kontrollerer det maksimale antal processer, der kan køre. Er aldrig nødvendigt til normale programmer."</string>
+ <string name="permdesc_setProcessLimit" msgid="7824786028557379539">"Tillader, at en applikation kontrollerer det maksimale antal processer, der kan køre. Er aldrig nødvendigt til normale applikationer."</string>
<string name="permlab_setAlwaysFinish" msgid="5342837862439543783">"få alle baggrundsprogrammer til at lukke"</string>
- <string name="permdesc_setAlwaysFinish" msgid="8773936403987091620">"Tillader, at et program kontrollerer, om aktiviteter altid afsluttes, så snart de går i baggrunden. Aldrig nødvendigt til normale programmer."</string>
+ <string name="permdesc_setAlwaysFinish" msgid="8773936403987091620">"Tillader, at en applikation kontrollerer, om aktiviteter altid afsluttes, så snart de går i baggrunden. Aldrig nødvendigt til normale applikationer."</string>
<string name="permlab_batteryStats" msgid="7863923071360031652">"rediger batteristatistikker"</string>
- <string name="permdesc_batteryStats" msgid="5847319823772230560">"Tillader ændring af indsamlede batteristatistikker. Ikke til brug for normale programmer."</string>
+ <string name="permdesc_batteryStats" msgid="5847319823772230560">"Tillader ændring af indsamlede batteristatistikker. Ikke til brug for normale applikationer."</string>
<string name="permlab_backup" msgid="470013022865453920">"kontroller sikkerhedskopiering af system, og gendan"</string>
- <string name="permdesc_backup" msgid="4837493065154256525">"Tillader, at et program kontrollerer systemets sikkerhedskopierings- og gendannelsesfunktion. Ikke til brug til normale programmer."</string>
+ <string name="permdesc_backup" msgid="4837493065154256525">"Tillader, at en applikation kontrollerer systemets sikkerhedskopierings- og gendannelsesfunktion. Ikke til brug til normale applikationer."</string>
<string name="permlab_confirm_full_backup" msgid="5557071325804469102">"bekræfte en komplet sikkerhedskopi, eller gendan drift"</string>
- <string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Tillader, at programmet starter brugergrænsefladen til bekræftelse af komplet backup. Må ikke anvendes af et program."</string>
+ <string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Tillader, at applikationen starter brugergrænsefladen til bekræftelse af komplet backup. Må ikke anvendes af en applikation."</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"vis uautoriserede vinduer"</string>
- <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Tillader oprettelse af vinduer, der er beregnet til at blive brugt af den interne systembrugergrænseflade. Ikke til brug for normale programmer."</string>
+ <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Tillader oprettelse af vinduer, der er beregnet til at blive brugt af den interne systembrugergrænseflade. Ikke til brug for normale applikationer."</string>
<string name="permlab_systemAlertWindow" msgid="3372321942941168324">"vis underretninger på systemniveau"</string>
- <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Tillader, at et program viser vinduer med systemunderretninger. Ondsindede programmer kan overtage hele skærmen."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Tillader, at en applikation viser vinduer med systemunderretninger. Ondsindede applikationer kan overtage hele skærmen."</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"rediger global animationshastighed"</string>
- <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Tillader, at et program altid kan ændre den globale animationshastighed (hurtigere eller langsommere animationer)."</string>
+ <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Tillader, at en applikation altid kan ændre den globale animationshastighed (hurtigere eller langsommere animationer)."</string>
<string name="permlab_manageAppTokens" msgid="17124341698093865">"administrer programtokens"</string>
- <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Tillader, at programmet opretter og administrerer sine egen tokens og gå uden om sin normale Z-rækkefølge. Bør aldrig være nødvendigt til normale programmer."</string>
+ <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Tillader, at applikationen opretter og administrerer sine egen tokens og gå uden om sin normale Z-rækkefølge. Bør aldrig være nødvendigt til normale applikationer."</string>
<string name="permlab_injectEvents" msgid="1378746584023586600">"tryk på taster og kontrolknapper"</string>
- <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Tillader, at et program leverer sine egne inputbegivenheder (tastetryk osv.) til andre programmer. Ondsindede programmer kan bruge dette til at overtage tabletcomputeren."</string>
- <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Tillader, at et program leverer sine egne inputbegivenheder (tastetryk osv.) til andre programmer. Ondsindede programmer kan bruge dette til at overtage telefonen."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Tillader, at en applikation leverer sine egne inputbegivenheder (tastetryk osv.) til andre applikationer. Ondsindede applikationer kan bruge dette til at overtage tabletcomputeren."</string>
+ <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Tillader, at en applikation leverer sine egne inputbegivenheder (tastetryk osv.) til andre applikationer. Ondsindede applikationer kan bruge dette til at overtage telefonen."</string>
<string name="permlab_readInputState" msgid="469428900041249234">"registrerer, hvad du indtaster, og hvilke handlinger du foretager dig"</string>
- <string name="permdesc_readInputState" msgid="5132879321450325445">"Tillader, at et program registrerer taster, du trykker på, selv når du interagerer med andre programmer (f.eks. ved indtastning af adgangskode). Bør aldrig være nødvendigt til normale programmer."</string>
+ <string name="permdesc_readInputState" msgid="5132879321450325445">"Tillader, at en applikation registrerer taster, du trykker på, selv når du interagerer med andre applikationer (f.eks. ved indtastning af adgangskode). Bør aldrig være nødvendigt til normale applikationer."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"forpligt til en inputmetode"</string>
- <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Tillader, at brugeren forpligter sig til en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendig til normale programmer."</string>
+ <string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Tillader, at brugeren forpligter sig til en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendig til normale applikationer."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"forpligt til et tapet"</string>
- <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Tillader, at brugeren forpligter sig til et tapets grænseflade på øverste niveau. Bør aldrig være nødvendig til normale programmer."</string>
+ <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Tillader, at brugeren forpligter sig til et tapets grænseflade på øverste niveau. Bør aldrig være nødvendig til normale applikationer."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
<string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Tillader, at brugeren forpligter sig til en widgettjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige applikationer."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
- <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Tillader brugeren at sende hensigter til en enhedsadministrator. Bør aldrig være nødvendigt for almindelige programmer."</string>
+ <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Tillader brugeren at sende hensigter til en enhedsadministrator. Bør aldrig være nødvendigt for almindelige applikationer."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"skift skærmretning"</string>
- <string name="permdesc_setOrientation" msgid="6335814461615851863">"Tillader, at et program ændrer rotationen af skærmen når som helst. Bør aldrig være nødvendigt til normale programmer."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
- <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"send Linux-signaler til programmer"</string>
- <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Tillader, at programmet kan anmode om, at det leverede signal sendes til alle vedholdende processer."</string>
- <string name="permlab_persistentActivity" msgid="8659652042401085862">"lad altid programmet køre"</string>
- <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Tillader, at et program gør dele af sig selv vedholdende, så systemet ikke kan bruge det til andre programmer."</string>
- <string name="permlab_deletePackages" msgid="3343439331576348805">"slet programmer"</string>
- <string name="permdesc_deletePackages" msgid="3634943677518723314">"Tillader, at et program sletter Android-pakker. Ondsindede programmer kan bruge dette til at slette vigtige programmer."</string>
+ <string name="permdesc_setOrientation" msgid="6335814461615851863">"Tillader, at en applikation ændrer rotationen af skærmen når som helst. Bør aldrig være nødvendigt til normale applikationer."</string>
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ændre markørens hastighed"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Tillader, at en applikation altid kan ændre muse- eller pegefeltmarkørens hastighed. Burde ikke være nødvendigt i normale applikationer."</string>
+ <string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"send Linux-signaler til applikationer"</string>
+ <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Tillader, at applikationen kan anmode om, at det leverede signal sendes til alle vedholdende processer."</string>
+ <string name="permlab_persistentActivity" msgid="8659652042401085862">"lad altid applikationen køre"</string>
+ <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Tillader, at en applikation gør dele af sig selv vedholdende, så systemet ikke kan bruge det til andre applikationer."</string>
+ <string name="permlab_deletePackages" msgid="3343439331576348805">"slet applikationer"</string>
+ <string name="permdesc_deletePackages" msgid="3634943677518723314">"Tillader, at en applikation sletter Android-pakker. Ondsindede applikationer kan bruge dette til at slette vigtige applikationer."</string>
<string name="permlab_clearAppUserData" msgid="2192134353540277878">"slet andre programmers data"</string>
- <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Tillader, at et program rydder brugerdata."</string>
+ <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Tillader, at en applikation rydder brugerdata."</string>
<string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"slet andre programmers cacher"</string>
- <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Tillader, at et program sletter cachefiler."</string>
+ <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Tillader, at en applikation sletter cachefiler."</string>
<string name="permlab_getPackageSize" msgid="4799785352306641460">"vis programmets lagerplads"</string>
- <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Tillader, at et program henter sin kode, data og cachestørrelser"</string>
- <string name="permlab_installPackages" msgid="335800214119051089">"installer programmer direkte"</string>
- <string name="permdesc_installPackages" msgid="526669220850066132">"Tillader, at et program installerer nye eller opdaterede Android-pakker. Ondsindede programmer kan bruge dette til at tilføje nye programmer med vilkårlige, effektive tilladelser."</string>
- <string name="permlab_clearAppCache" msgid="4747698311163766540">"slet alle cachedata for programmet"</string>
- <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Tillader, at et program frigør plads på tabletcomputeren ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser."</string>
- <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Tillader, at et program frigør plads på telefonen ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser."</string>
+ <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Tillader, at en applikation henter sin kode, data og cachestørrelser"</string>
+ <string name="permlab_installPackages" msgid="335800214119051089">"installer applikationer direkte"</string>
+ <string name="permdesc_installPackages" msgid="526669220850066132">"Tillader, at en applikation installerer nye eller opdaterede Android-pakker. Ondsindede applikationer kan bruge dette til at tilføje nye applikationer med vilkårlige, effektive tilladelser."</string>
+ <string name="permlab_clearAppCache" msgid="4747698311163766540">"slet alle cachedata for applikationen"</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Tillader, at en applikation frigør plads på tabletcomputeren ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser."</string>
+ <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Tillader, at en applikation frigør plads på telefonen ved at slette filer i programmets cachemappe. Adgang er normalt meget begrænset til systemprocesser."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Flyt programressourcer"</string>
- <string name="permdesc_movePackage" msgid="6323049291923925277">"Tillader, at et program flytter programressourcer fra interne til eksterne medier og omvendt."</string>
+ <string name="permdesc_movePackage" msgid="6323049291923925277">"Tillader, at en applikation flytter programressourcer fra interne til eksterne medier og omvendt."</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"læse følsomme logdata"</string>
- <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Tillader, at et program læser fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med tabletcomputeren, registreres, også personlige eller private oplysninger."</string>
- <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Tillader, at et program læser fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med telefonen, registreres, også personlige eller private oplysninger."</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Tillader, at en applikation læser fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med tabletcomputeren, registreres, også personlige eller private oplysninger."</string>
+ <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Tillader, at en applikation læser fra systemets forskellige logfiler. Dermed kan generelle oplysninger om, hvad du laver med telefonen, registreres, også personlige eller private oplysninger."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"læs/skriv til ressourcer ejet af diag"</string>
- <string name="permdesc_diagnostic" msgid="3121238373951637049">"Tillader, at et program læser og skriver til alle ressourcer, der ejes af diag-gruppen, som f.eks. flier i /dev. Dette kan muligvis påvirke systemets stabilitet og sikkerhed. Dette bør KUN bruges til hardwarespecifikke diagnosticeringer foretaget af producent eller udbyder."</string>
+ <string name="permdesc_diagnostic" msgid="3121238373951637049">"Tillader, at en applikation læser og skriver til alle ressourcer, der ejes af diag-gruppen, som f.eks. flier i /dev. Dette kan muligvis påvirke systemets stabilitet og sikkerhed. Dette bør KUN bruges til hardwarespecifikke diagnosticeringer foretaget af producent eller udbyder."</string>
<string name="permlab_changeComponentState" msgid="79425198834329406">"aktiver eller deaktiver programkomponenter"</string>
- <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Tillader, at et program ændrer, om en komponent fra et andet program er aktiveret eller ej. Ondsindede programmer kan bruge dette til at deaktivere vigtige funktioner på tabletcomputeren. Denne tilladelse skal anvendes med forsigtighed, da det kan forårsage ubrugelige, inkonsekvente eller ustabile programkomponenter."</string>
- <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Tillader, at et program ændrer, om en komponent fra et andet program er aktiveret eller ej. Ondsindede programmer kan bruge dette til at deaktivere vigtige funktioner på telefonen. Denne tilladelse skal anvendes med forsigtighed, da det kan forårsage ubrugelige eller ustabile programkomponenter."</string>
- <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"angiv foretrukne programmer"</string>
- <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Tillader, at et program ændrer dine foretrukne programmer. Dette kan medføre, at ondsindede programmer ændrer kørende programmer i det skjulte og narrer dine eksisterende programmer til at indsamle personlige oplysninger fra dig."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Tillader, at en applikation ændrer, om en komponent fra en anden applikation er aktiveret eller ej. Ondsindede applikationer kan bruge dette til at deaktivere vigtige funktioner på tabletcomputeren. Denne tilladelse skal anvendes med forsigtighed, da det kan forårsage ubrugelige, inkonsekvente eller ustabile programkomponenter."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Tillader, at en applikation ændrer, om en komponent fra en anden applikation er aktiveret eller ej. Ondsindede applikationer kan bruge dette til at deaktivere vigtige funktioner på telefonen. Denne tilladelse skal anvendes med forsigtighed, da det kan forårsage ubrugelige eller ustabile programkomponenter."</string>
+ <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"angiv foretrukne applikationer"</string>
+ <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Tillader, at en applikation ændrer dine foretrukne applikationer. Dette kan medføre, at ondsindede applikationer ændrer kørende applikationer i det skjulte og narrer dine eksisterende applikationer til at indsamle personlige oplysninger fra dig."</string>
<string name="permlab_writeSettings" msgid="1365523497395143704">"rediger globale systemindstillinger"</string>
- <string name="permdesc_writeSettings" msgid="838789419871034696">"Tillader, at et program ændrer systemets indstillingsdata. Ondsindede programmer kan skade systemets konfiguration."</string>
+ <string name="permdesc_writeSettings" msgid="838789419871034696">"Tillader, at en applikation ændrer systemets indstillingsdata. Ondsindede applikationer kan skade systemets konfiguration."</string>
<string name="permlab_writeSecureSettings" msgid="204676251876718288">"rediger sikre systemindstillinger"</string>
- <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Tillader, at et program ændrer systemernes sikre indstillingsdata. Ikke til brug til almindelige programmer."</string>
+ <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Tillader, at en applikation ændrer systemernes sikre indstillingsdata. Ikke til brug til almindelige applikationer."</string>
<string name="permlab_writeGservices" msgid="2149426664226152185">"rediger kortet over Google-tjenester"</string>
- <string name="permdesc_writeGservices" msgid="6602362746516676175">"Tillader, at et program ændrer kortet over Google-tjenester. Ikke til brug til normale programmer."</string>
+ <string name="permdesc_writeGservices" msgid="6602362746516676175">"Tillader, at en applikation ændrer kortet over Google-tjenester. Ikke til brug til normale applikationer."</string>
<string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"start automatisk ved opstart"</string>
- <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Tillader, at et program selv starter, når systemet er færdig med at starte. Dette kan gøre opstarten af tabletcomputeren langsommere og generelt gøre tabletcomputeren langsommere ved altid at lade programmet køre."</string>
- <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Tillader, at et program starter selv, når systemet er færdig med at starte. Dette kan gøre startem af telefonen langsommere og generelt gøre telefonen langsommere ved altid at lade programmet køre."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Tillader, at en applikation selv starter, når systemet er færdig med at starte. Dette kan gøre opstarten af tabletcomputeren langsommere og generelt gøre tabletcomputeren langsommere ved altid at lade applikationen køre."</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Tillader, at en applikation starter selv, når systemet er færdig med at starte. Dette kan gøre startem af telefonen langsommere og generelt gøre telefonen langsommere ved altid at lade applikationen køre."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"send klæbende udsendelse"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Tillader, at et program sender klæbende udsendelser, der bliver tilbage, efter udsendelsen er slut. Ondsindede programmer kan gøre tabletcomputeren langsom eller ustabil ved at få den til at bruge for meget hukommelse."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Tillader, at et program sender klæbende udsendelser, der bliver tilbage, efter udsendelsen er slut. Ondsindede programmer kan gøre telefonen langsom eller ustabil ved at få den til at bruge for meget hukommelse."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Tillader, at en applikation sender klæbende udsendelser, der bliver tilbage, efter udsendelsen er slut. Ondsindede applikationer kan gøre tabletcomputeren langsom eller ustabil ved at få den til at bruge for meget hukommelse."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Tillader, at en applikation sender klæbende udsendelser, der bliver tilbage, efter udsendelsen er slut. Ondsindede applikationer kan gøre telefonen langsom eller ustabil ved at få den til at bruge for meget hukommelse."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"læs kontaktdata"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Tillader, at et program læser alle kontaktdata (adresser), der er gemt på din tabletcomputer. Ondsindede programmer kan bruge dette til at sende dine data til andre mennesker."</string>
- <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Tillader, at et program læser alle kontaktdata (adresser), der er gemt på din telefon. Ondsindede programmer kan bruge dette til at sende dine data til andre mennesker."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Tillader, at en applikation læser alle kontaktdata (adresser), der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at sende dine data til andre mennesker."</string>
+ <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Tillader, at en applikation læser alle kontaktdata (adresser), der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at sende dine data til andre mennesker."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"skriv kontaktdata"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Tillader, at et program ændrer kontaktdata (adresser), der er gemt på din tabletcomputer. Ondsindede programmer kan bruge dette til at slette eller ændre kontaktdata."</string>
- <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Tillader, at et program ændrer kontaktdata (adresser), der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Tillader, at en applikation ændrer kontaktdata (adresser), der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at slette eller ændre kontaktdata."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Tillader, at en applikation ændrer kontaktdata (adresser), der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at slette eller ændre kontaktdata."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"læs kalenderbegivenheder"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Tillader, at et program læser alle kalenderbegivenheder, der er gemt på din tabletcomputer. Ondsindede programmer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
- <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Tillader, at et program læser alle kalenderbegivenheder, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Tillader, at en applikation læser alle kalenderbegivenheder, der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
+ <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Tillader, at en applikation læser alle kalenderbegivenheder, der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at sende dine kalenderbegivenheder til andre mennesker."</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"tilføj eller rediger kalenderbegivenheder, og send e-mail til gæster"</string>
- <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Tillader, at et program tilføjer eller ændrer begivenhederne i din kalender, hvilket kan sende e-mail til gæster. Ondsindede programmer kan bruge dette til at slette eller ændre dine kalenderbegivenheder eller til at sende e-mail til gæster."</string>
+ <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Tillader, at en applikation tilføjer eller ændrer begivenhederne i din kalender, hvilket kan sende e-mail til gæster. Ondsindede applikationer kan bruge dette til at slette eller ændre dine kalenderbegivenheder eller til at sende e-mail til gæster."</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"imiterede placeringskilder til test"</string>
- <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Opret imiterede placeringskilder til testning. Ondsindede programmer kan bruge dette til at tilsidesætte den returnerede placering og/eller status fra rigtige placeringskilder som f.eks. GPS eller netværksudbydere."</string>
+ <string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Opret imiterede placeringskilder til testning. Ondsindede applikationer kan bruge dette til at tilsidesætte den returnerede placering og/eller status fra rigtige placeringskilder som f.eks. GPS eller netværksudbydere."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"få adgang til yderligere kommandoer for placeringsudbyder"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Få adgang til ekstra kommandoer fra placeringsudbyder. Ondsindede programmer kan bruge dette til at gribe ind i driften af GPS\'en eller andre placeringskilder."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="1948144701382451721">"Få adgang til ekstra kommandoer fra placeringsudbyder. Ondsindede applikationer kan bruge dette til at gribe ind i driften af GPS\'en eller andre placeringskilder."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"tilladelse til at installere en placeringsudbyder"</string>
- <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Opret imiterede placeringskilder til testning. Ondsindede programmer kan bruge dette til at tilsidesætte den returnerede placering og/eller status fra rigtige placeringskilder som f.eks. GPS eller netværksudbydere eller til at overvåge og rapportere din placering til en ekstern kilde."</string>
+ <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Opret imiterede placeringskilder til testning. Ondsindede applikationer kan bruge dette til at tilsidesætte den returnerede placering og/eller status fra rigtige placeringskilder som f.eks. GPS eller netværksudbydere eller til at overvåge og rapportere din placering til en ekstern kilde."</string>
<string name="permlab_accessFineLocation" msgid="8116127007541369477">"fin (GPS) placering"</string>
- <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Få adgang til gode placeringskilder, som f.eks. Global Positioning System på tabletcomputeren, hvor det er tilgængeligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du er, og kan eventuelt bruge yderligere batterikapacitet."</string>
- <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Få adgang til gode placeringskilder, som f.eks. Global Positioning System på telefonen, når det er tilgængeligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du er og kan eventuelt bruge yderligere batterikapacitet."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Få adgang til gode placeringskilder, som f.eks. Global Positioning System på tabletcomputeren, hvor det er tilgængeligt. Ondsindede applikationer kan bruge dette til at finde ud af, hvor du er, og kan eventuelt bruge yderligere batterikapacitet."</string>
+ <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Få adgang til gode placeringskilder, som f.eks. Global Positioning System på telefonen, når det er tilgængeligt. Ondsindede applikationer kan bruge dette til at finde ud af, hvor du er og kan eventuelt bruge yderligere batterikapacitet."</string>
<string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"grov (netværksbaseret) placering"</string>
- <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Få adgang til grove placeringskilder som f.eks. den mobile netværksdatabase for at finde en omtrentlig placering for tabletcomputeren, hvor det er muligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du omtrent er."</string>
- <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Få adgang til grove placeringskilder som f.eks. den mobile netværksdatabase for at finde en omtrentlig placering for telefonen, hvor det er muligt. Ondsindede programmer kan bruge dette til at finde ud af, hvor du omtrent er."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Få adgang til grove placeringskilder som f.eks. den mobile netværksdatabase for at finde en omtrentlig placering for tabletcomputeren, hvor det er muligt. Ondsindede applikationer kan bruge dette til at finde ud af, hvor du omtrent er."</string>
+ <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Få adgang til grove placeringskilder som f.eks. den mobile netværksdatabase for at finde en omtrentlig placering for telefonen, hvor det er muligt. Ondsindede applikationer kan bruge dette til at finde ud af, hvor du omtrent er."</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få adgang til SurfaceFlinger"</string>
- <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Tillader, at et program bruger SurfaceFlinger-funktioner på lavt niveau."</string>
+ <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Tillader, at en applikation bruger SurfaceFlinger-funktioner på lavt niveau."</string>
<string name="permlab_readFrameBuffer" msgid="6690504248178498136">"læs rammebuffer"</string>
- <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Tillader, at et program læser indholdet fra rammebufferen."</string>
+ <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Tillader, at en applikation læser indholdet fra rammebufferen."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"skift dine lydindstillinger"</string>
- <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Tillader, at et program ændrer globale lydindstillinger som f.eks. lydstyrke og kanalisering."</string>
+ <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Tillader, at en applikation ændrer globale lydindstillinger som f.eks. lydstyrke og kanalisering."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"optag lyd"</string>
- <string name="permdesc_recordAudio" msgid="6493228261176552356">"Tillader, at et program får adgang til lydregistreringsstien."</string>
+ <string name="permdesc_recordAudio" msgid="6493228261176552356">"Tillader, at en applikation får adgang til lydregistreringsstien."</string>
<string name="permlab_camera" msgid="3616391919559751192">"tag billeder og optag video"</string>
- <string name="permdesc_camera" msgid="6004878235852154239">"Tillader, at programmet tager billeder og optager video med kameraet. Dette giver programmet mulighed for altid at indsamle de billeder, kameraet ser."</string>
+ <string name="permdesc_camera" msgid="6004878235852154239">"Tillader, at applikationen tager billeder og optager video med kameraet. Dette giver applikationen mulighed for altid at indsamle de billeder, kameraet ser."</string>
<string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktiver tabletcomputeren permanent"</string>
<string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktiver telefonen permanent"</string>
- <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Tillader, at programmet deaktiverer hele tabletcomputeren permanent. Dette er meget farligt."</string>
- <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Tillader, at programmet deaktiverer hele telefonen permanent. Dette er meget farligt."</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Tillader, at applikationen deaktiverer hele tabletcomputeren permanent. Dette er meget farligt."</string>
+ <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Tillader, at applikationen deaktiverer hele telefonen permanent. Dette er meget farligt."</string>
<string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"tving tabletcomputeren til at genstarte"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"tving telefon til at genstarte"</string>
- <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Tillader, at programmet tvinger tabletcomputeren til at genstarte."</string>
- <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Tillader, at programmet tvinger telefonen til at genstarte."</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Tillader, at applikationen tvinger tabletcomputeren til at genstarte."</string>
+ <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Tillader, at applikationen tvinger telefonen til at genstarte."</string>
<string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"monter eller demonter filsystemer"</string>
- <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Tillader, at programmet monterer eller demonterer filsystemer til flytbar lagring."</string>
+ <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Tillader, at applikationen monterer eller demonterer filsystemer til flytbar lagring."</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formater ekstern lagring"</string>
- <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Tillader, at et program formaterer flytbart lager."</string>
+ <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Tillader, at en applikation formaterer flytbart lager."</string>
<string name="permlab_asec_access" msgid="3411338632002193846">"hente oplysninger om internt lager"</string>
- <string name="permdesc_asec_access" msgid="8820326551687285439">"Tillader, at programmet får oplysninger om internt lager."</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Tillader, at applikationen får oplysninger om internt lager."</string>
<string name="permlab_asec_create" msgid="6414757234789336327">"oprette internt lager"</string>
- <string name="permdesc_asec_create" msgid="2621346764995731250">"Tillader, at programmet opretter internt lager."</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Tillader, at applikationen opretter internt lager."</string>
<string name="permlab_asec_destroy" msgid="526928328301618022">"ødelægge internt lager"</string>
- <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Tillader, at programmet ødelægger internt lager."</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Tillader, at applikationen ødelægger internt lager."</string>
<string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montere/demontere internt lager"</string>
- <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Tillader, at programmet monterer/demonterer internt lager."</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Tillader, at applikationen monterer/demonterer internt lager."</string>
<string name="permlab_asec_rename" msgid="7496633954080472417">"omdøbe internt lager"</string>
- <string name="permdesc_asec_rename" msgid="2152829985238876790">"Tillader, at programmet omdøber internt lager."</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Tillader, at applikationen omdøber internt lager."</string>
<string name="permlab_vibrate" msgid="7768356019980849603">"kontroller vibrator"</string>
- <string name="permdesc_vibrate" msgid="2886677177257789187">"Lader programmet kontrollere vibratoren."</string>
+ <string name="permdesc_vibrate" msgid="2886677177257789187">"Lader applikationen kontrollere vibratoren."</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"kontroller lommelygte"</string>
- <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillader, at programmet kontrollerer lommelygten."</string>
+ <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillader, at applikationen kontrollerer lommelygten."</string>
<string name="permlab_manageUsb" msgid="1113453430645402723">"administrer præferencer og tilladelser for USB-enheder"</string>
- <string name="permdesc_manageUsb" msgid="6148489202092166164">"Tillader, at programmet administrerer præferencer og tilladelser for USB-enheder."</string>
+ <string name="permdesc_manageUsb" msgid="6148489202092166164">"Tillader, at applikationen administrerer præferencer og tilladelser for USB-enheder."</string>
<string name="permlab_accessMtp" msgid="4953468676795917042">"implementere MTP-protokol"</string>
<string name="permdesc_accessMtp" msgid="6532961200486791570">"Tillader adgang til kerne-MTP-driveren for at implementere MTB USB-protokollen."</string>
<string name="permlab_hardware_test" msgid="4148290860400659146">"test hardware"</string>
- <string name="permdesc_hardware_test" msgid="3668894686500081699">"Tillader, at et program kontrollerer forskellige perifere enheder for at teste hardwaren."</string>
+ <string name="permdesc_hardware_test" msgid="3668894686500081699">"Tillader, at en applikation kontrollerer forskellige perifere enheder for at teste hardwaren."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"ring direkte op til telefonnumre"</string>
- <string name="permdesc_callPhone" msgid="3369867353692722456">"Tillader, at programmet ringer til telefonnumre uden din indgriben. Ondsindede programmer kan forårsage uventede opkald på din telefonregning. Vær opmærksom på, at programmet ikke kan ringe til nødnumre."</string>
+ <string name="permdesc_callPhone" msgid="3369867353692722456">"Tillader, at applikationen ringer til telefonnumre uden din indgriben. Ondsindede applikationer kan forårsage uventede opkald på din telefonregning. Vær opmærksom på, at applikationen ikke kan ringe til nødnumre."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"ring direkte op til alle telefonnumre"</string>
- <string name="permdesc_callPrivileged" msgid="244405067160028452">"Tillader, at programmet ringer til alle telefonnumre inklusive nødnumre uden din indgriben. Ondsindede programmer kan eventuelt foretage unødvendige og ulovlige opkald til nødtjenester."</string>
+ <string name="permdesc_callPrivileged" msgid="244405067160028452">"Tillader, at applikationen ringer til alle telefonnumre inklusive nødnumre uden din indgriben. Ondsindede applikationer kan eventuelt foretage unødvendige og ulovlige opkald til nødtjenester."</string>
<string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"start CDMA-opsætning af tabletcomputeren direkte"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"start CDMA-telefonopsætning direkte"</string>
- <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Tillader, at programmet starter CDMA-levering. Ondsindede programmer kan starte unødvendig CDMA-levering"</string>
+ <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Tillader, at applikationen starter CDMA-levering. Ondsindede applikationer kan starte unødvendig CDMA-levering"</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"kontroller meddelelser om placeringsopdatering"</string>
- <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Tillader aktivering/deaktivering af placeringsdata fra radioen. Ikke til brug til normale programmer."</string>
+ <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Tillader aktivering/deaktivering af placeringsdata fra radioen. Ikke til brug til normale applikationer."</string>
<string name="permlab_checkinProperties" msgid="7855259461268734914">"egenskaber for adgangskontrol"</string>
- <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Tillader læse/skrive-adgang til egenskaber, der er uploadet af kontroltjenesten. Ikke til brug til normale programmer."</string>
+ <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Tillader læse/skrive-adgang til egenskaber, der er uploadet af kontroltjenesten. Ikke til brug til normale applikationer."</string>
<string name="permlab_bindGadget" msgid="776905339015863471">"vælg widgets"</string>
- <string name="permdesc_bindGadget" msgid="2098697834497452046">"Tillader, at programmet fortæller systemet, hvilke widgets der kan bruges af hvilke programmer. Med denne tilladelse kan programmer give adgang til personlige oplysninger til andre programmer. Ikke til brug til normale programmer."</string>
+ <string name="permdesc_bindGadget" msgid="2098697834497452046">"Tillader, at applikationen fortæller systemet, hvilke widgets der kan bruges af hvilke applikationer. Med denne tilladelse kan applikationer give adgang til personlige oplysninger til andre applikationer. Ikke til brug til normale applikationer."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"rediger telefontilstand"</string>
- <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Tillader, at programmet kontrollerer enhedens telefonfunktioner. Et program med denne tilladelse kan skifte netværk, slå telefonens radio til og fra og lignende uden nogensinde at informere dig."</string>
+ <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Tillader, at applikationen kontrollerer enhedens telefonfunktioner. En applikation med denne tilladelse kan skifte netværk, slå telefonens radio til og fra og lignende uden nogensinde at informere dig."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"læs telefontilstand og identitet"</string>
- <string name="permdesc_readPhoneState" msgid="188877305147626781">"Tillader, at programmet får adgang til enhedens telefonfunktioner. Et program kan med denne tilladelse registrere denne telefons telefon- og serienummer, om et opkald er aktivt, nummeret som det opkald er forbundet til osv."</string>
+ <string name="permdesc_readPhoneState" msgid="188877305147626781">"Tillader, at applikationen får adgang til enhedens telefonfunktioner. En applikation kan med denne tilladelse registrere denne telefons telefon- og serienummer, om et opkald er aktivt, nummeret som det opkald er forbundet til osv."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"afhold tabletcomputeren fra at gå i dvale"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"afhold telefonen fra at gå i dvale"</string>
- <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Tillader, at et program forhindrer tabletcomputeren i at gå i dvale."</string>
- <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Tillader, at et program forhindrer telefonen i at gå i dvale."</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Tillader, at en applikation forhindrer tabletcomputeren i at gå i dvale."</string>
+ <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Tillader, at en applikation forhindrer telefonen i at gå i dvale."</string>
<string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"tænd eller sluk for tabletcomputeren"</string>
<string name="permlab_devicePower" product="default" msgid="4928622470980943206">"tænd eller sluk for telefonen"</string>
- <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Tillader, at programmet slukker og tænder tabletcomputeren."</string>
- <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Tillader, at programmet slukker og tænder telefonen."</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Tillader, at applikationen slukker og tænder tabletcomputeren."</string>
+ <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Tillader, at applikationen slukker og tænder telefonen."</string>
<string name="permlab_factoryTest" msgid="3715225492696416187">"kør i fabriksindstillet testtilstand"</string>
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Kør som en producenttest på lavt niveau, der giver fuld adgang til tabletcomputerens hardware. Kun tilgængeligt når en tabletcomputer kører i producenttesttilstand."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Kør som en producenttest på lavt niveau. Giver fuld adgang til telefonens hardware. Kun tilgængeligt når en telefon kører i producenttesttilstand."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"angiv tapet"</string>
- <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Tillader, at programmet opsætter systemets tapet."</string>
+ <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Tillader, at applikationen opsætter systemets tapet."</string>
<string name="permlab_setWallpaperHints" msgid="3600721069353106851">"opsæt tip til tapetstørrelse"</string>
- <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Tillader, at programmet opsætter størrelsestip for systemets tapet."</string>
+ <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Tillader, at applikationen opsætter størrelsestip for systemets tapet."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"nulstil system til fabriksstandarder"</string>
- <string name="permdesc_masterClear" msgid="5033465107545174514">"Tillader, at et program nulstiller systemet fuldstændig til fabriksindstillingerne, sletter alle data, konfigurationer og installerede programmer."</string>
+ <string name="permdesc_masterClear" msgid="5033465107545174514">"Tillader, at en applikation nulstiller systemet fuldstændig til fabriksindstillingerne, sletter alle data, konfigurationer og installerede applikationer."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"angive tid"</string>
- <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Tillader, at et program ændrer tabletcomputerens klokkeslæt."</string>
- <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Tillader, at et program ændrer telefonens klokkeslæt."</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Tillader, at en applikation ændrer tabletcomputerens klokkeslæt."</string>
+ <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Tillader, at en applikation ændrer telefonens klokkeslæt."</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"angiv tidszone"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Tillader, at et program ændrer tabletcomputerens tidszone."</string>
- <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Tillader, at et program ændrer telefonens tidszone."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Tillader, at en applikation ændrer tabletcomputerens tidszone."</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Tillader, at en applikation ændrer telefonens tidszone."</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"fungerer som kontoadministrationstjeneste"</string>
- <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Tillader, at et program foretager opkald til kontogodkendere"</string>
+ <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Tillader, at en applikation foretager opkald til kontogodkendere"</string>
<string name="permlab_getAccounts" msgid="4549918644233460103">"registrer kendte konti"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Tillader, at et program henter listen over konti, der er kendt af tabletcomputeren."</string>
- <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Tillader, at et program henter listen over konti, der er kendt af telefonen."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Tillader, at en applikation henter listen over konti, der er kendt af tabletcomputeren."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Tillader, at en applikation henter listen over konti, der er kendt af telefonen."</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"fungerer som en kontogodkender"</string>
- <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Tillader, at et program bruger kontoadministratorens kontogodkendelsesegenskaber, bl.a. oprettelse af konti samt hentning og indstilling af deres adgangskoder."</string>
+ <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Tillader, at en applikation bruger kontoadministratorens kontogodkendelsesegenskaber, bl.a. oprettelse af konti samt hentning og indstilling af deres adgangskoder."</string>
<string name="permlab_manageAccounts" msgid="4440380488312204365">"administrer kontolisten"</string>
- <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Tillader, at et program foretager handlinger, f.eks. at tilføje og fjerne konti samt slette sin adgangskode."</string>
+ <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Tillader, at en applikation foretager handlinger, f.eks. at tilføje og fjerne konti samt slette sin adgangskode."</string>
<string name="permlab_useCredentials" msgid="6401886092818819856">"brug en kontos godkendelsesoplysninger"</string>
- <string name="permdesc_useCredentials" msgid="7416570544619546974">"Tillader, at et program anmoder om godkendelsestokens"</string>
+ <string name="permdesc_useCredentials" msgid="7416570544619546974">"Tillader, at en applikation anmoder om godkendelsestokens"</string>
<string name="permlab_accessNetworkState" msgid="6865575199464405769">"vis netværkstilstand"</string>
- <string name="permdesc_accessNetworkState" msgid="558721128707712766">"Tillader, at et program viser tilstanden for alle netværk."</string>
+ <string name="permdesc_accessNetworkState" msgid="558721128707712766">"Tillader, at en applikation viser tilstanden for alle netværk."</string>
<string name="permlab_createNetworkSockets" msgid="9121633680349549585">"fuld internetadgang"</string>
- <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"Tillader, at et program opretter netværks-sockets."</string>
+ <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"Tillader, at en applikation opretter netværks-sockets."</string>
<string name="permlab_writeApnSettings" msgid="7823599210086622545">"skriv indstillinger for adgangspunktnavn"</string>
- <string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Tillader, at et program ændrer APN-indstillingerne, f.eks. enhver APNs Proxy og Port."</string>
+ <string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Tillader, at en applikation ændrer APN-indstillingerne, f.eks. enhver APNs Proxy og Port."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"skift netværksforbindelse"</string>
- <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Tillader, at et program ændrer netværksforbindelsens tilstand."</string>
+ <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Tillader, at en applikation ændrer netværksforbindelsens tilstand."</string>
<string name="permlab_changeTetherState" msgid="2702121155761140799">"Skift tethering-forbindelse"</string>
- <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Tillader, at et program ændrer tilstand for et bundet netværk."</string>
+ <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Tillader, at en applikation ændrer tilstand for et bundet netværk."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"skift brugerindstilling for baggrundsdata"</string>
- <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Tillader, at et program ændrer brugerindstillingerne for baggrundsdata."</string>
+ <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Tillader, at en applikation ændrer brugerindstillingerne for baggrundsdata."</string>
<string name="permlab_accessWifiState" msgid="8100926650211034400">"vis Wi-Fi-tilstand"</string>
- <string name="permdesc_accessWifiState" msgid="485796529139236346">"Tillader, at et program viser oplysninger om Wi-Fi-tilstanden."</string>
+ <string name="permdesc_accessWifiState" msgid="485796529139236346">"Tillader, at en applikation viser oplysninger om Wi-Fi-tilstanden."</string>
<string name="permlab_changeWifiState" msgid="7280632711057112137">"skift Wi-Fi-tilstand"</string>
- <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Tillader, at et program opretter og afbryder forbindelsen fra Wi-Fi-adgangspunkter og foretager ændringer i konfigurerede Wi-Fi-netværk."</string>
+ <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Tillader, at en applikation opretter og afbryder forbindelsen fra Wi-Fi-adgangspunkter og foretager ændringer i konfigurerede Wi-Fi-netværk."</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"tillad Wi-Fi-multicastmodtagelse"</string>
- <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Tillader, at et program modtager pakker, der ikke er direkte adresseret til din enhed. Dette kan være nyttigt, hvis du finder tjenester, der tilbydes i nærheden. Det bruger mere strøm end multicasttilstanden."</string>
+ <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Tillader, at en applikation modtager pakker, der ikke er direkte adresseret til din enhed. Dette kan være nyttigt, hvis du finder tjenester, der tilbydes i nærheden. Det bruger mere strøm end multicasttilstanden."</string>
<string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"bluetooth-administration"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Tillader, at et program konfigurerer den lokale Bluetooth-tabletcomputer samt opdager og parrer med fjerne enheder."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Tillader, at et program konfigurerer den lokale Bluetooth-telefon samt opdager og parrer med fjerne enheder."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Tillader, at en applikation konfigurerer den lokale Bluetooth-tabletcomputer samt opdager og parrer med fjerne enheder."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Tillader, at en applikation konfigurerer den lokale Bluetooth-telefon samt opdager og parrer med fjerne enheder."</string>
<string name="permlab_bluetooth" msgid="8361038707857018732">"opret Bluetooth-forbindelser"</string>
- <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Tillader, at et program viser konfigurationen af den lokale Bluetooth-tabletcomputer samt opretter og accepterer forbindelse med parrede enheder."</string>
- <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Tillader, at et program viser konfigurationen af den lokale Bluetooth-telefon samt opretter og accepterer forbindelse med parrede enheder."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Tillader, at en applikation viser konfigurationen af den lokale Bluetooth-tabletcomputer samt opretter og accepterer forbindelse med parrede enheder."</string>
+ <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Tillader, at en applikation viser konfigurationen af den lokale Bluetooth-telefon samt opretter og accepterer forbindelse med parrede enheder."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"kontrollere Near Field Communication"</string>
- <string name="permdesc_nfc" msgid="9171401851954407226">"Tillader, at et program kommunikerer med tags, kort og læsere i Near Field Communication (NFC)."</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Tillader, at en applikation kommunikerer med tags, kort og læsere i Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"opfange og ændre al netværkstrafik"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Tillader, at et program opfanger og kontrollerer al netværkstrafik, f.eks. for at oprette en VPN-forbindelse. Ondsindede programmer kan overvåge, omdirigere eller ændre netværkspakker uden din viden."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Tillader, at en applikation opfanger og kontrollerer al netværkstrafik for at oprette en VPN-forbindelse. Ondsindede applikationer kan overvåge, omdirigere eller ændre netværkspakker uden din viden."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"deaktiver tastaturlås"</string>
- <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillader, at et program deaktiverer tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet."</string>
+ <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillader, at en applikation deaktiverer tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"læs indstillinger for synkronisering"</string>
- <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Tillader, at et program læser synkroniseringsindstillingerne, f.eks. om kontakter skal synkroniseres."</string>
+ <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Tillader, at en applikation læser synkroniseringsindstillingerne, f.eks. om kontakter skal synkroniseres."</string>
<string name="permlab_writeSyncSettings" msgid="6297138566442486462">"skriv indstillinger for synkronisering"</string>
- <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Tillader, at et program ændrer indstillingerne for synkronisering, f.eks. kontakter skal synkroniseres."</string>
+ <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Tillader, at en applikation ændrer indstillingerne for synkronisering, f.eks. kontakter skal synkroniseres."</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"læs synkroniseringsstatistikker"</string>
- <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Tillader, at et program læser synkroniseringsstatistikker, f.eks. oversigten over forrige synkroniseringer."</string>
+ <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Tillader, at en applikation læser synkroniseringsstatistikker, f.eks. oversigten over forrige synkroniseringer."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"læs abonnerede feeds"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Tillader, at et program får detaljer om de aktuelt synkroniserede feeds."</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Tillader, at en applikation får detaljer om de aktuelt synkroniserede feeds."</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"skriv abonnerede feeds"</string>
- <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Tillader, at et program ændrer dine aktuelle synkroniserede feeds. Dette kan muligvis lade et ondsindet program ændre dine synkroniserede feeds."</string>
+ <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Tillader, at en applikation ændrer dine aktuelle synkroniserede feeds. Dette kan muligvis lade et ondsinden applikation ændre dine synkroniserede feeds."</string>
<string name="permlab_readDictionary" msgid="432535716804748781">"læs brugerdefineret ordbog"</string>
- <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillader, at et program læser alle private ord, navne og sætninger, som brugeren eventuelt har gemt i brugerordbogen."</string>
+ <string name="permdesc_readDictionary" msgid="1082972603576360690">"Tillader, at en applikation læser alle private ord, navne og sætninger, som brugeren eventuelt har gemt i brugerordbogen."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"skriv til den brugerdefinerede ordbog"</string>
- <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillader, at et program skriver nye ord i brugerordbogen."</string>
+ <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Tillader, at en applikation skriver nye ord i brugerordbogen."</string>
<string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"rette/slette i USB-lager"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ret/slet indholdet på SD-kortet"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Tillad skriv til USB-lager."</string>
- <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillader, at et program skriver til SD-kortet."</string>
+ <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Tillader, at en applikation skriver til SD-kortet."</string>
<string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Rediger/slet internt medielagringsindhold"</string>
<string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Tillader, at applikationen ændrer indholdet af det interne medielagringsindhold."</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"få adgang til cache-filsystemet"</string>
- <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillader, at et program læser og skriver til cache-filsystemet."</string>
+ <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillader, at en applikation læser og skriver til cache-filsystemet."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"foretage/modtage internetopkald"</string>
- <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillader, at et program anvender SIP-tjenesten til at foretage/modtage internetopkald."</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Tillader, at en applikation anvender SIP-tjenesten til at foretage/modtage internetopkald."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærm"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Administrer, hvor tit skærmlåsens adgangskode skal skiftes"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angiv kryptering af lager"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kræv, at gemte programdata krypteres"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Hjem"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbejde"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Andre"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Indtast PIN-kode"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Angiv PUK- og ny PIN-kode"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Ny PIN-kode"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Indtast adgangskode her"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Indtast adgangskode for at låse op"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Indtast pinkode for at låse op"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Der er ikke noget SIM-kort i tabletcomputeren."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Der er ikke noget SIM-kort i telefonen."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Indsæt et SIM-kort."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Kun nødopkald"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netværket er låst"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet er låst med PUK-koden."</string>
@@ -682,14 +712,14 @@
<string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
<string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og bogmærker"</string>
- <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at programmet læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillader, at applikationen læser alle de webadresser, browseren har besøgt, og alle browserens bogmærker."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriv browserens oversigt og bogmærker"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Tillader, at et program ændrer browseroversigten eller bogmærker, der er gemt på din tabletcomputer. Ondsindede programmer kan bruge dette til at slette eller ændre din browsers data."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Tillader, at et program ændrer browseroversigten eller bogmærker, der er gemt på din telefon. Ondsindede programmer kan bruge dette til at slette eller ændre din browsers data."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Tillader, at en applikation ændrer browseroversigten eller bogmærker, der er gemt på din tabletcomputer. Ondsindede applikationer kan bruge dette til at slette eller ændre din browsers data."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Tillader, at en applikation ændrer browseroversigten eller bogmærker, der er gemt på din telefon. Ondsindede applikationer kan bruge dette til at slette eller ændre din browsers data."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"angiv alarm i alarmprogram"</string>
- <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillader, at programmet angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
+ <string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillader, at applikationen angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Skift browsertilladelser for geografisk placering"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Giver et program tilladelse til at ændre browserens tilladelser for geografisk placering. Skadelige programmer kan bruge dette til at tillade, at placeringsoplysninger sendes til vilkårlige websteder."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Giver en applikation tilladelse til at ændre browserens tilladelser for geografisk placering. Skadelige applikationer kan bruge dette til at tillade, at placeringsoplysninger sendes til vilkårlige websteder."</string>
<string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ikke nu"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
@@ -822,15 +852,15 @@
<string name="capital_off" msgid="6815870386972805832">"FRA"</string>
<string name="whichApplication" msgid="4533185947064773386">"Fuldfør handling ved hjælp af"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Brug som standard til denne handling."</string>
- <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Ryd standard i Startindstillinger > Programmer > Administrer programmer."</string>
+ <string name="clearDefaultHintMsg" msgid="4815455344600932173">"Ryd standard i Startindstillinger > Applikationer > Administrer applikationer."</string>
<string name="chooseActivity" msgid="1009246475582238425">"Vælg en handling"</string>
- <string name="chooseUsbActivity" msgid="7892597146032121735">"Vælg et program for USB-enheden"</string>
- <string name="noApplications" msgid="1691104391758345586">"Der er ingen programmer, der kan foretage denne handling."</string>
+ <string name="chooseUsbActivity" msgid="7892597146032121735">"Vælg en applikation for USB-enheden"</string>
+ <string name="noApplications" msgid="1691104391758345586">"Der er ingen applikationer, der kan foretage denne handling."</string>
<string name="aerr_title" msgid="653922989522758100">"Beklager!"</string>
<string name="aerr_application" msgid="4683614104336409186">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) er standset uventet. Prøv igen."</string>
<string name="aerr_process" msgid="1551785535966089511">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> er standset uventet. Prøv igen."</string>
<string name="anr_title" msgid="3100070910664756057">"Beklager!"</string>
- <string name="anr_activity_application" msgid="3538242413112507636">"Aktivitet <xliff:g id="ACTIVITY">%1$s</xliff:g> (i programmet <xliff:g id="APPLICATION">%2$s</xliff:g>) svarer ikke."</string>
+ <string name="anr_activity_application" msgid="3538242413112507636">"Aktivitet <xliff:g id="ACTIVITY">%1$s</xliff:g> (i applikationen <xliff:g id="APPLICATION">%2$s</xliff:g>) svarer ikke."</string>
<string name="anr_activity_process" msgid="5420826626009561014">"Aktivitet <xliff:g id="ACTIVITY">%1$s</xliff:g> (igangværende <xliff:g id="PROCESS">%2$s</xliff:g>) svarer ikke."</string>
<string name="anr_application_process" msgid="4185842666452210193">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (igangværende <xliff:g id="PROCESS">%2$s</xliff:g>) svarer ikke."</string>
<string name="anr_process" msgid="1246866008169975783">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> svarer ikke."</string>
@@ -849,13 +879,13 @@
<string name="smv_application" msgid="295583804361236288">"Programmet <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) har overtrådt sin egen StrictMode-politik."</string>
<string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har overtrådt sin egen StrictMode-politik."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> er i gang"</string>
- <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Vælg for at skifte program"</string>
- <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Skift program?"</string>
- <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Der kører et andet program, der skal stoppes, før du kan starte et nyt."</string>
+ <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Vælg for at skifte applikation"</string>
+ <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Skift applikation?"</string>
+ <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Der kører en anden applikation, der skal stoppes, før du kan starte et nyt."</string>
<string name="old_app_action" msgid="493129172238566282">"Tilbage til <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
- <string name="old_app_description" msgid="942967900237208466">"Start ikke det nye program."</string>
+ <string name="old_app_description" msgid="942967900237208466">"Start ikke den nye applikation."</string>
<string name="new_app_action" msgid="5472756926945440706">"Start <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
- <string name="new_app_description" msgid="6830398339826789493">"Stop det gamle program uden at gemme."</string>
+ <string name="new_app_description" msgid="6830398339826789493">"Stop den gamle applikation uden at gemme."</string>
<string name="sendText" msgid="5132506121645618310">"Vælg en handling for teksten"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Lydstyrke for opkald"</string>
<string name="volume_music" msgid="5421651157138628171">"Lydstyrke for medier"</string>
@@ -880,7 +910,7 @@
<item quantity="other" msgid="7915895323644292768">"Der er åbne Wi-Fi-netværk tilgængelige"</item>
</plurals>
<string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
- <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukendt program"</string>
+ <string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukendt applikation"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
<string name="sms_control_message" msgid="1289331457999236205">"Der sendes et stort antal sms-beskeder. Vælg \"OK\" for at fortsætte eller \"Annuller\" for at stoppe afsendelsen."</string>
<string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
@@ -921,9 +951,13 @@
<string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Slå USB-lagring fra"</string>
<string name="usb_storage_stop_error_message" msgid="143881914840412108">"Der opstod et problem med at slå USB-lagringen fra. Sørg for, at du har demonteret USB-værten, og prøv så igen."</string>
<string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Slå USB-lagring til"</string>
- <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de programmer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string>
+ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du slår USB-lagring til, vil nogle af de applikationer, som du bruger, stoppe, og de kan være utilgængelige, indtil du slår USB-lagring til igen."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-handlingen mislykkedes"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater USB-lager"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater SD-kort"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lager og slette alle filer, som er gemt der? Handlingen kan ikke fortrydes!"</string>
@@ -961,9 +995,9 @@
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortet er fjernet. Indsæt et nyt."</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Der blev ikke fundet nogen matchende aktiviteter"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"opdater brugerstatistikker for komponenter"</string>
- <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Tillader ændring af indsamlede brugerstatistikker for komponenter. Ikke til brug til normale programmer."</string>
- <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Tillader kald af standardcontainertjeneste for at kopiere indhold. Ikke til brug for almindelige programmer."</string>
- <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Tillader kald af standardcontainertjeneste for at kopiere indhold. Ikke til brug for almindelige programmer."</string>
+ <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Tillader ændring af indsamlede brugerstatistikker for komponenter. Ikke til brug til normale applikationer."</string>
+ <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Tillader kald af standardcontainertjeneste for at kopiere indhold. Ikke til brug for almindelige applikationer."</string>
+ <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Tillader kald af standardcontainertjeneste for at kopiere indhold. Ikke til brug for almindelige applikationer."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tryk to gange for zoomkontrol"</string>
<string name="gadget_host_error_inflating" msgid="2613287218853846830">"Der opstod en fejl under forøgelsen af widgetten"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Gå"</string>
@@ -975,7 +1009,7 @@
<string name="ime_action_default" msgid="2840921885558045721">"Udfør"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Ring til nummer"\n"ved hjælp af <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Opret kontakt"\n"ved hjælp af <xliff:g id="NUMBER">%s</xliff:g>"</string>
- <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"Følgende programmer anmoder om tilladelse til at få adgang til din konto nu og i fremtiden."</string>
+ <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"Følgende applikationer anmoder om tilladelse til at få adgang til din konto nu og i fremtiden."</string>
<string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Vil du tillade denne anmodning?"</string>
<string name="grant_permissions_header_text" msgid="2722567482180797717">"Adgangsanmodning"</string>
<string name="allow" msgid="7225948811296386551">"Tillad"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN baseret på forhåndsdelt nøglekodning"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certifikatbaseret L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
<string name="reset" msgid="2448168080964209908">"Nulstil"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Internt lager"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-lager"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediger..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Sikkerhedscertifikat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dette certifikat er gyldigt."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Udstedt til:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Fællesnavn:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisatorisk enhed:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Udstedt af:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Gyldighed:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Udstedt den:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Udløber den:"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b6b6be5..9753482 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Der von Ihnen eingegebene PUK ist nicht korrekt."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Die von Ihnen eingegebenen PIN-Nummern stimmen nicht überein."</string>
<string name="invalidPin" msgid="3850018445187475377">"Geben Sie eine PIN ein, die 4 bis 8 Zahlen enthält."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Geben Sie eine mindestens achtstellige PUK ein."</string>
<string name="needPuk" msgid="919668385956251611">"Ihre SIM-Karte ist mit einem PUK gesperrt. Geben Sie zum Entsperren den PUK-Code ein."</string>
<string name="needPuk2" msgid="4526033371987193070">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Anrufer-ID für eingehenden Anruf"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"Mehr als 100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Mehr als 100"</string>
<string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
@@ -179,80 +180,84 @@
<string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Zugriff auf USB-Speicher"</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Zugriff auf SD-Karte"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
- <string name="permdesc_statusBar" msgid="1365473595331989732">"Ermöglicht der Anwendung, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
+ <string name="permdesc_statusBar" msgid="1365473595331989732">"Ermöglicht der App, die Statusanzeige zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="7247281911387931485">"Statusleiste"</string>
- <string name="permdesc_statusBarService" msgid="4097605867643520920">"Ermöglicht der Anwendung, zur Statusleiste zu werden"</string>
+ <string name="permdesc_statusBarService" msgid="4097605867643520920">"Ermöglicht der App, zur Statusleiste zu werden"</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"Statusleiste ein-/ausblenden"</string>
- <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Ermöglicht der Anwendung, die Statusleiste ein- oder auszublenden"</string>
+ <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Ermöglicht der App, die Statusleiste ein- oder auszublenden"</string>
<string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"Ausgehende Anrufe abfangen"</string>
- <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Ermöglicht einer Anwendung, abgehende Anrufe zu verarbeiten und die zu wählende Nummer zu ändern. Schädliche Anwendungen können so abgehende Anrufe eventuell überwachen, umleiten oder verhindern."</string>
+ <string name="permdesc_processOutgoingCalls" msgid="2228988201852654461">"Ermöglicht einer App, abgehende Anrufe zu verarbeiten und die zu wählende Nummer zu ändern. Schädliche Anwendungen können so abgehende Anrufe eventuell überwachen, umleiten oder verhindern."</string>
<string name="permlab_receiveSms" msgid="2697628268086208535">"SMS empfangen"</string>
- <string name="permdesc_receiveSms" msgid="6298292335965966117">"Ermöglicht der Anwendung, Kurzmitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
+ <string name="permdesc_receiveSms" msgid="6298292335965966117">"Ermöglicht der App, Kurzmitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMS empfangen"</string>
- <string name="permdesc_receiveMms" msgid="4563346832000174373">"Ermöglicht der Anwendung, MMS-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
+ <string name="permdesc_receiveMms" msgid="4563346832000174373">"Ermöglicht der App, MMS-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"Notfall-Broadcasts empfangen"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Ermöglicht einer App, Notfall-Broadcasts zu empfangen und zu verarbeiten. Diese Berechtigung steht nur Systemanwendungen zur Verfügung."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"Kurznachrichten senden"</string>
- <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht der Anwendung das Senden von SMS. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
+ <string name="permdesc_sendSms" msgid="1946540351763502120">"Ermöglicht der App das Senden von SMS. Bei schädlichen Anwendungen können Kosten entstehen, wenn diese Nachrichten ohne Ihre Zustimmung versenden."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMS oder MMS lesen"</string>
- <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ermöglicht einer Anwendung, auf Ihrem Tablet oder Ihrer SIM-Karte gespeicherte SMS zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre vertraulichen Nachrichten."</string>
- <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ermöglicht einer Anwendung, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre vertraulichen Nachrichten."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ermöglicht einer App, auf Ihrem Tablet oder Ihrer SIM-Karte gespeicherte SMS zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre vertraulichen Nachrichten."</string>
+ <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ermöglicht einer App, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu lesen. Schädliche Anwendungen lesen so möglicherweise Ihre vertraulichen Nachrichten."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"SMS oder MMS bearbeiten"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ermöglicht einer Anwendung, auf Ihrem Tablet oder Ihrer SIM-Karte gespeicherte SMS zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
- <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ermöglicht einer Anwendung, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ermöglicht einer App, auf Ihrem Tablet oder Ihrer SIM-Karte gespeicherte SMS zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
+ <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ermöglicht einer App, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte Kurznachrichten zu bearbeiten. Schädliche Anwendungen löschen möglicherweise Ihre Nachrichten."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"WAP-Nachrichten empfangen"</string>
- <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Ermöglicht der Anwendung, WAP-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
+ <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Ermöglicht der App, WAP-Mitteilungen zu empfangen und zu verarbeiten. Schädliche Anwendungen können Ihre Nachrichten möglicherweise überwachen oder löschen, bevor sie angezeigt werden."</string>
<string name="permlab_getTasks" msgid="5005277531132573353">"laufende Anwendungen abrufen"</string>
- <string name="permdesc_getTasks" msgid="7048711358713443341">"Ermöglicht der Anwendung, Informationen zu aktuellen und kürzlich ausführten Aufgaben abzurufen. Schädliche Anwendungen können so eventuell geheime Informationen zu anderen Anwendungen entdecken."</string>
+ <string name="permdesc_getTasks" msgid="7048711358713443341">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausführten Aufgaben abzurufen. Schädliche Anwendungen können so eventuell geheime Informationen zu anderen Anwendungen entdecken."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"Laufende Anwendungen neu ordnen"</string>
- <string name="permdesc_reorderTasks" msgid="126252774270522835">"Ermöglicht einer Anwendung, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Anwendungen können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
+ <string name="permdesc_reorderTasks" msgid="126252774270522835">"Ermöglicht einer App, Aufgaben in den Vorder- und Hintergrund zu verschieben. Schädliche Anwendungen können so ohne Ihr Zutun eine Anzeige im Vordergrund erzwingen."</string>
<string name="permlab_removeTasks" msgid="4802740047161700683">"Aktive Apps beenden"</string>
<string name="permdesc_removeTasks" msgid="2000332928514575461">"Ermöglicht einer App das Entfernen von Aufgaben und Beenden der entsprechenden Apps. Schädliche Apps können das Verhalten anderer Apps stören."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"Fehlerbeseitigung für Anwendung aktivieren"</string>
- <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Ermöglicht einer Anwendung, die Fehlerbeseitigung für eine andere Anwendung zu aktivieren. Schädliche Anwendungen können so andere Anwendungen löschen."</string>
+ <string name="permdesc_setDebugApp" msgid="5584310661711990702">"Ermöglicht einer App, die Fehlerbeseitigung für eine andere Anwendung zu aktivieren. Schädliche Anwendungen können so andere Anwendungen löschen."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI-Einstellungen ändern"</string>
- <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Ermöglicht einer Anwendung, die aktuelle Konfiguration zu ändern, etwa das Gebietsschema oder die Schriftgröße"</string>
+ <string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Ermöglicht einer App, die aktuelle Konfiguration zu ändern, etwa das Gebietsschema oder die Schriftgröße"</string>
<string name="permlab_enableCarMode" msgid="5684504058192921098">"Automodus aktivieren"</string>
- <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Ermöglicht einer Anwendung, den Automodus zu aktivieren"</string>
+ <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Ermöglicht einer App, den Automodus zu aktivieren"</string>
<string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"Hintergrundprozesse beenden"</string>
- <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ermöglicht einer Anwendung, Hintergrundprozesse anderer Anwendungen auch bei ausreichendem Speicher zu beenden."</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ermöglicht einer App, Hintergrundprozesse anderer Anwendungen auch bei ausreichendem Speicher zu beenden."</string>
<string name="permlab_forceStopPackages" msgid="1447830113260156236">"Beenden anderer Anwendungen erzwingen"</string>
- <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Ermöglicht einer Anwendung, das Beenden anderer Anwendungen zu erzwingen"</string>
+ <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Ermöglicht einer App, das Beenden anderer Anwendungen zu erzwingen"</string>
<string name="permlab_forceBack" msgid="1804196839880393631">"Schließen von Anwendung erzwingen"</string>
- <string name="permdesc_forceBack" msgid="6534109744159919013">"Ermöglicht einer Anwendung, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden."</string>
+ <string name="permdesc_forceBack" msgid="6534109744159919013">"Ermöglicht einer App, alle Aktivitäten, die im Vordergrund ablaufen, zu beenden und in den Hintergrund zu schieben. Sollte nicht für normale Anwendungen benötigt werden."</string>
<string name="permlab_dump" msgid="1681799862438954752">"Systeminternen Status abrufen"</string>
- <string name="permdesc_dump" msgid="2198776174276275220">"Ermöglicht einer Anwendung, den internen Status des Systems abzurufen. Schädliche Anwendungen rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string>
+ <string name="permdesc_dump" msgid="2198776174276275220">"Ermöglicht einer App, den internen Status des Systems abzurufen. Schädliche Anwendungen rufen hierbei möglicherweise eine Vielzahl an privaten und geschützten Daten ab, die Sie in der Regel nicht benötigen würden."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Ermöglicht einer App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"partielles Herunterfahren"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"Anwendungswechsel verhindern"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Hindert den Nutzer daran, zu einer anderen Anwendung zu wechseln"</string>
<string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"Start von Anwendungen überwachen und steuern"</string>
- <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ermöglicht der Anwendung, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Anwendungen können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Nutzung benötigt."</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ermöglicht der App, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Anwendungen können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Nutzung benötigt."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Broadcast ohne Paket senden"</string>
- <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ermöglicht einer Anwendung, eine Benachrichtigung zur Entfernung eines Anwendungspakets zu senden. Schädliche Anwendungen können so laufende Anwendungen beenden."</string>
+ <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ermöglicht einer App, eine Benachrichtigung zur Entfernung eines Anwendungspakets zu senden. Schädliche Anwendungen können so laufende Anwendungen beenden."</string>
<string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"per SMS empfangenen Broadcast senden"</string>
- <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Ermöglicht einer Anwendung, eine Benachrichtigung zu senden, dass eine Kurzmitteilung empfangen wurde. Schädliche Anwendungen könnten diese Option verwenden, um den Eingang von Kurzmitteilungen zu erzwingen."</string>
+ <string name="permdesc_broadcastSmsReceived" msgid="9122419277306740155">"Ermöglicht einer App, eine Benachrichtigung zu senden, dass eine Kurzmitteilung empfangen wurde. Schädliche Anwendungen könnten diese Option verwenden, um den Eingang von Kurzmitteilungen zu erzwingen."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"von WAP-PUSH empfangenen Broadcast senden"</string>
- <string name="permdesc_broadcastWapPush" msgid="3955303669461378091">"Ermöglicht einer Anwendung, eine Benachrichtigung zu senden, dass eine WAP PUSH-Nachricht empfangen wurde. Schädliche Anwendungen könnten diese Option verwenden, um den Erhalt von MMS-Mitteilungen zu erzwingen, oder um unbemerkt den Inhalt einer beliebigen Webseite durch schädliche Inhalte zu ersetzen."</string>
+ <string name="permdesc_broadcastWapPush" msgid="3955303669461378091">"Ermöglicht einer App, eine Benachrichtigung zu senden, dass eine WAP PUSH-Nachricht empfangen wurde. Schädliche Anwendungen könnten diese Option verwenden, um den Erhalt von MMS-Mitteilungen zu erzwingen, oder um unbemerkt den Inhalt einer beliebigen Webseite durch schädliche Inhalte zu ersetzen."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"Anzahl der laufenden Prozesse beschränken"</string>
- <string name="permdesc_setProcessLimit" msgid="7824786028557379539">"Ermöglicht einer Anwendung, die maximale Anzahl an laufenden Prozessen zu steuern. Wird nicht für normale Anwendungen benötigt."</string>
+ <string name="permdesc_setProcessLimit" msgid="7824786028557379539">"Ermöglicht einer App, die maximale Anzahl an laufenden Prozessen zu steuern. Wird nicht für normale Anwendungen benötigt."</string>
<string name="permlab_setAlwaysFinish" msgid="5342837862439543783">"alle Anwendungen im Hintergrund schließen"</string>
<string name="permdesc_setAlwaysFinish" msgid="8773936403987091620">"Überlässt einer Anwendung die Entscheidung, ob Aktivitäten beendet werden, sobald Sie in den Hintergrund rücken. Wird nicht für normale Anwendungen benötigt."</string>
<string name="permlab_batteryStats" msgid="7863923071360031652">"Akku-Daten ändern"</string>
- <string name="permdesc_batteryStats" msgid="5847319823772230560">"Ermöglicht die Änderung von gesammelten Akku-Daten. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_batteryStats" msgid="5847319823772230560">"Ermöglicht die Änderung von gesammelten Akku-Daten. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_backup" msgid="470013022865453920">"Systemsicherung und -wiederherstellung kontrollieren"</string>
- <string name="permdesc_backup" msgid="4837493065154256525">"Der Anwendung wird die Steuerung des Sicherungs- und Wiederherstellungsmechanismus des Systems ermöglicht. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_backup" msgid="4837493065154256525">"Der Anwendung wird die Steuerung des Sicherungs- und Wiederherstellungsmechanismus des Systems ermöglicht. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_confirm_full_backup" msgid="5557071325804469102">"Vollständige Sicherung oder Wiederherstellung bestätigen"</string>
<string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Ermöglicht der App den Start der Benutzeroberfläche zur Bestätigung der vollständigen Sicherung. Kann nicht von jeder App verwendet werden."</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"nicht autorisierte Fenster anzeigen"</string>
- <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ermöglicht die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Anwendungen geeignet."</string>
+ <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ermöglicht die Erstellung von Fenstern, die von der Benutzeroberfläche des internen Systems verwendet werden. Nicht für normale Apps geeignet."</string>
<string name="permlab_systemAlertWindow" msgid="3372321942941168324">"Warnungen auf Systemebene anzeigen"</string>
- <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ermöglicht einer Anwendung, Fenster mit Systemwarnungen anzuzeigen. Schädliche Anwendungen können so die Kontrolle über das gesamte Display übernehmen."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ermöglicht einer App, Fenster mit Systemwarnungen anzuzeigen. Schädliche Anwendungen können so die Kontrolle über das gesamte Display übernehmen."</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"Allgemeine Animationsgeschwindigkeit einstellen"</string>
- <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ermöglicht einer Anwendung, die allgemeine Animationsgeschwindigkeit (schnellere oder langsamere Animationen) jederzeit anzupassen"</string>
+ <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ermöglicht einer App, die allgemeine Animationsgeschwindigkeit (schnellere oder langsamere Animationen) jederzeit anzupassen"</string>
<string name="permlab_manageAppTokens" msgid="17124341698093865">"Anwendungs-Tokens verwalten"</string>
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Ermöglicht Anwendungen, Ihre eigenen Tokens zu erstellen und zu verwalten. Hierbei wird die normale Z-Reihenfolge umgangen. Dies sollte nicht für normale Anwendungen benötigt werden."</string>
<string name="permlab_injectEvents" msgid="1378746584023586600">"Tasten und Steuerungstasten drücken"</string>
- <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ermöglicht einer Anwendung, ihre eigenen Eingabeaktionen (Drücken von Tasten usw.) an andere Anwendungen zu liefern. Schädliche Anwendungen können so die Kontrolle über Ihr Tablet übernehmen."</string>
- <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ermöglicht einer Anwendung, ihre eigenen Eingabeaktionen (Drücken von Tasten etc.) an andere Anwendungen zu liefern. Schädliche Anwendungen können so die Kontrolle über Ihr Telefon übernehmen."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ermöglicht einer App, ihre eigenen Eingabeaktionen (Drücken von Tasten usw.) an andere Anwendungen zu liefern. Schädliche Anwendungen können so die Kontrolle über Ihr Tablet übernehmen."</string>
+ <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ermöglicht einer App, ihre eigenen Eingabeaktionen (Drücken von Tasten etc.) an andere Anwendungen zu liefern. Schädliche Anwendungen können so die Kontrolle über Ihr Telefon übernehmen."</string>
<string name="permlab_readInputState" msgid="469428900041249234">"Tastatureingaben und Aktionen aufzeichnen"</string>
<string name="permdesc_readInputState" msgid="5132879321450325445">"Ermöglicht Anwendungen, die von Ihnen gedrückten Tasten zu überwachen (etwa die Eingabe eines Passworts). Dies gilt auch für die Interaktion mit anderen Anwendungen. Sollte für normale Anwendungen nicht benötigt werden."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"An eine Eingabemethode binden"</string>
@@ -264,63 +269,69 @@
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Interaktion mit einem Geräteadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Ermöglicht dem Halter, Intents an einen Geräteadministrator zu senden. Sollte nie für normale Anwendungen benötigt werden."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"Bildschirmausrichtung ändern"</string>
- <string name="permdesc_setOrientation" msgid="6335814461615851863">"Ermöglicht der Anwendung, die Bildschirmdrehung jederzeit zu ändern. Sollte nicht für normale Anwendungen benötigt werden."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permdesc_setOrientation" msgid="6335814461615851863">"Ermöglicht der App, die Bildschirmdrehung jederzeit zu ändern. Sollte nicht für normale Anwendungen benötigt werden."</string>
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Zeigergeschwindigkeit ändern"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Ermöglicht einer App, jederzeit die Geschwindigkeit des Maus- bzw. Touchpad-Zeigers zu ändern. Sollte für normale Apps nicht benötigt werden."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux-Signale an Anwendungen senden"</string>
- <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Ermöglicht der Anwendung, das Senden des gelieferten Signals an alle anhaltenden Prozesse zu fordern"</string>
+ <string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Ermöglicht der App, das Senden des gelieferten Signals an alle anhaltenden Prozesse zu fordern"</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"Anwendungen permanent ausführen"</string>
- <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Ermöglicht einer Anwendung, eigene Komponenten persistent zu machen, damit das System diese nicht für andere Anwendungen nutzen kann"</string>
+ <string name="permdesc_persistentActivity" msgid="5037199778265006008">"Ermöglicht einer App, eigene Komponenten persistent zu machen, damit das System diese nicht für andere Anwendungen nutzen kann"</string>
<string name="permlab_deletePackages" msgid="3343439331576348805">"Anwendungen löschen"</string>
- <string name="permdesc_deletePackages" msgid="3634943677518723314">"Ermöglicht einer Anwendung, Android-Pakete zu löschen. Schädliche Anwendungen können so wichtige Anwendungen löschen."</string>
+ <string name="permdesc_deletePackages" msgid="3634943677518723314">"Ermöglicht einer App, Android-Pakete zu löschen. Schädliche Anwendungen können so wichtige Anwendungen löschen."</string>
<string name="permlab_clearAppUserData" msgid="2192134353540277878">"Daten anderer Anwendungen löschen"</string>
- <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Ermöglicht einer Anwendung das Löschen von Nutzerdaten"</string>
+ <string name="permdesc_clearAppUserData" msgid="7546345080434325456">"Ermöglicht einer App das Löschen von Nutzerdaten"</string>
<string name="permlab_deleteCacheFiles" msgid="1518556602634276725">"Caches anderer Anwendungen löschen"</string>
- <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Ermöglicht einer Anwendung, Cache-Dateien zu löschen"</string>
+ <string name="permdesc_deleteCacheFiles" msgid="2283074077168165971">"Ermöglicht einer App, Cache-Dateien zu löschen"</string>
<string name="permlab_getPackageSize" msgid="4799785352306641460">"Speicherplatz der Anwendung abrufen"</string>
- <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Ermöglicht einer Anwendung, ihre Code-, Daten- und Cache-Größe abzurufen"</string>
+ <string name="permdesc_getPackageSize" msgid="5557253039670753437">"Ermöglicht einer App, ihre Code-, Daten- und Cache-Größe abzurufen"</string>
<string name="permlab_installPackages" msgid="335800214119051089">"Anwendungen direkt installieren"</string>
- <string name="permdesc_installPackages" msgid="526669220850066132">"Ermöglicht einer Anwendung, neue oder aktualisierte Android-Pakete zu installieren. Schädliche Anwendungen können so neue Anwendungen mit beliebig umfangreichen Berechtigungen hinzufügen."</string>
+ <string name="permdesc_installPackages" msgid="526669220850066132">"Ermöglicht einer App, neue oder aktualisierte Android-Pakete zu installieren. Schädliche Anwendungen können so neue Anwendungen mit beliebig umfangreichen Berechtigungen hinzufügen."</string>
<string name="permlab_clearAppCache" msgid="4747698311163766540">"Alle Cache-Daten der Anwendung löschen"</string>
- <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ermöglicht einer Anwendung, Tablet-Speicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
- <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ermöglicht einer Anwendung, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ermöglicht einer App, Tablet-Speicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
+ <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ermöglicht einer App, Telefonspeicher durch das Löschen von Dateien im Cache-Verzeichnis der Anwendung freizugeben. Der Zugriff beschränkt sich in der Regel auf Systemprozesse."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Anwendungsressourcen verschieben"</string>
- <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer Anwendung, Anwendungsressourcen von internen auf externe Medien zu verschieben und umgekehrt"</string>
+ <string name="permdesc_movePackage" msgid="6323049291923925277">"Ermöglicht einer App, Anwendungsressourcen von internen auf externe Medien zu verschieben und umgekehrt"</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"Lesen vertraulicher Protokolldaten"</string>
- <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ermöglicht einer Anwendung, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
- <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ermöglicht einer Anwendung, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ermöglicht einer App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Tablet durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
+ <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ermöglicht einer App, die verschiedenen Protokolldateien des Systems zu lesen. So können allgemeine Informationen zu den auf Ihrem Telefon durchgeführten Aktionen eingesehen werden. Diese können persönliche oder geheime Daten enthalten."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"Lese-/Schreibberechtigung für zu Diagnosegruppe gehörige Elemente"</string>
- <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ermöglicht einer Anwendung, alle Elemente in der Diagnosegruppe zu lesen und zu bearbeiten, etwa Dateien in \"/dev\". Dies könnte eine potenzielle Gefährdung für die Stabilität und Sicherheit des Systems darstellen und sollte NUR für Hardware-spezifische Diagnosen des Herstellers oder Netzbetreibers verwendet werden."</string>
+ <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ermöglicht einer App, alle Elemente in der Diagnosegruppe zu lesen und zu bearbeiten, etwa Dateien in \"/dev\". Dies könnte eine potenzielle Gefährdung für die Stabilität und Sicherheit des Systems darstellen und sollte NUR für Hardware-spezifische Diagnosen des Herstellers oder Netzbetreibers verwendet werden."</string>
<string name="permlab_changeComponentState" msgid="79425198834329406">"Anwendungskomponenten aktivieren oder deaktivieren"</string>
- <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ermöglicht einer Anwendung, die Komponente einer anderen Anwendung nach Belieben zu aktivieren oder zu deaktivieren. Schädliche Anwendungen können so wichtige Funktionen des Tablets deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die Anwendungskomponenten unbrauchbar, inkonsistent und instabil werden können."</string>
- <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ermöglicht einer Anwendung, die Komponente einer anderen Anwendung nach Belieben zu aktivieren oder zu deaktivieren. Schädliche Anwendungen können so wichtige Funktionen des Telefons deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die Anwendungskomponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ermöglicht einer App, die Komponente einer anderen Anwendung nach Belieben zu aktivieren oder zu deaktivieren. Schädliche Anwendungen können so wichtige Funktionen des Tablets deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die Anwendungskomponenten unbrauchbar, inkonsistent und instabil werden können."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ermöglicht einer App, die Komponente einer anderen Anwendung nach Belieben zu aktivieren oder zu deaktivieren. Schädliche Anwendungen können so wichtige Funktionen des Telefons deaktivieren. Bei der Erteilung dieser Berechtigung ist Vorsicht geboten, da die Anwendungskomponenten unbrauchbar, inkonsistent oder instabil werden können."</string>
<string name="permlab_setPreferredApplications" msgid="3393305202145172005">"bevorzugte Einstellungen festlegen"</string>
- <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ermöglicht einer Anwendung, Ihre bevorzugten Einstellungen zu ändern. Schädliche Anwendungen können so laufende Anwendungen ohne Ihr Wissen ändern, damit die vorhandenen Anwendungen private Daten von Ihnen sammeln."</string>
+ <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ermöglicht einer App, Ihre bevorzugten Einstellungen zu ändern. Schädliche Anwendungen können so laufende Anwendungen ohne Ihr Wissen ändern, damit die vorhandenen Anwendungen private Daten von Ihnen sammeln."</string>
<string name="permlab_writeSettings" msgid="1365523497395143704">"allgemeine Systemeinstellungen ändern"</string>
- <string name="permdesc_writeSettings" msgid="838789419871034696">"Ermöglicht einer Anwendung, die Einstellungsdaten des Systems zu ändern. Schädliche Anwendungen können so die Systemkonfiguration beschädigen."</string>
+ <string name="permdesc_writeSettings" msgid="838789419871034696">"Ermöglicht einer App, die Einstellungsdaten des Systems zu ändern. Schädliche Anwendungen können so die Systemkonfiguration beschädigen."</string>
<string name="permlab_writeSecureSettings" msgid="204676251876718288">"Sicherheitseinstellungen für das System ändern"</string>
- <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Der Anwendung wird das Ändern der Sicherheitseinstellungsdaten des Systems ermöglicht. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Der Anwendung wird das Ändern der Sicherheitseinstellungsdaten des Systems ermöglicht. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_writeGservices" msgid="2149426664226152185">"Google Services Map ändern"</string>
- <string name="permdesc_writeGservices" msgid="6602362746516676175">"Ermöglicht einer Anwendung, Änderungen an der Google Services Map vorzunehmen. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_writeGservices" msgid="6602362746516676175">"Ermöglicht einer App, Änderungen an der Google Services Map vorzunehmen. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"Automatisch nach dem Booten starten"</string>
- <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ermöglicht einer Anwendung, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Tablet gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Tablets beeinträchtigt."</string>
- <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ermöglicht einer Anwendung, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Telefon gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Telefons beeinträchtigt."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ermöglicht einer App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Tablet gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Tablets beeinträchtigt."</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ermöglicht einer App, sich selbst zu starten, sobald das System gebootet wurde. Dadurch kann es länger dauern, bis das Telefon gestartet wird, und durch die ständige Aktivität der Anwendung wird die gesamte Leistung des Telefons beeinträchtigt."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"dauerhaften Broadcast senden"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Tablet langsam oder instabil machen, da zu viel Speicherplatz belegt wird."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ermöglicht einer Anwendung, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Telefon langsam oder unstabil machen, da zuviel Speicherplatz belegt wird."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ermöglicht einer App, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Tablet langsam oder instabil machen, da zu viel Speicherplatz belegt wird."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ermöglicht einer App, dauerhafte Broadcasts zu senden, die auch nach dem Ende des Broadcasts bestehen bleiben. Schädliche Anwendungen können das Telefon langsam oder unstabil machen, da zuviel Speicherplatz belegt wird."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"Kontaktdaten lesen"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ermöglicht einer Anwendung, alle auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
- <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ermöglicht einer Anwendung, alle auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ermöglicht einer App, alle auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
+ <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ermöglicht einer App, alle auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu lesen. Schädliche Anwendungen können so Ihre Daten an andere Personen senden."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"Kontaktdaten schreiben"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ermöglicht einer Anwendung, die auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
- <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ermöglicht einer Anwendung, die auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ermöglicht einer App, die auf Ihrem Tablet gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
+ <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ermöglicht einer App, die auf Ihrem Telefon gespeicherten Kontaktdaten (Adressen) zu ändern. Schädliche Anwendungen können so Ihre Kontaktdaten löschen oder verändern."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"Kalendereinträge lesen"</string>
- <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ermöglicht einer Anwendung, alle auf Ihrem Tablet gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
- <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ermöglicht einer Anwendung, alle auf Ihrem Telefon gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ermöglicht einer App, alle auf Ihrem Tablet gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
+ <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ermöglicht einer App, alle auf Ihrem Telefon gespeicherten Kalenderereignisse zu lesen. Schädliche Anwendungen können so Ihre Kalenderereignisse an andere Personen senden."</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"Kalendereinträge hinzufügen oder ändern und E-Mails an Gäste senden"</string>
- <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ermöglicht einer Anwendung, Einträge in Ihrem Kalender hinzuzufügen oder zu ändern, wodurch E-Mails an Gäste gesendet werden können. Schädliche Anwendungen können so Ihre Kalenderdaten löschen oder verändern oder E-Mails versenden."</string>
+ <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ermöglicht einer App, Einträge in Ihrem Kalender hinzuzufügen oder zu ändern, wodurch E-Mails an Gäste gesendet werden können. Schädliche Anwendungen können so Ihre Kalenderdaten löschen oder verändern oder E-Mails versenden."</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"Simulierte Standortquellen für Testzwecke"</string>
<string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Erstellt falsche Standortquellen für Testzwecke. Schädliche Anwendungen können so den von den echten Standortquellen wie GPS oder Netzwerkanbieter zurückgegebenen Standort und/oder Status überschreiben."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen"</string>
@@ -334,152 +345,160 @@
<string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Greift auf Quellen mit ungefähren Standortbestimmungen wie die Datenbank des Mobilfunknetzes zu, um falls möglich den ungefähren Standort des Tablets zu bestimmen. Schädliche Anwendungen können damit herauszufinden, wo Sie sich ungefähr befinden."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Greift auf Quellen mit ungefähren Standortbestimmungen wie die Datenbank des Mobilfunknetzes zu, um falls möglich den ungefähren Standort des Tablets festzustellen. Schädliche Anwendungen können damit herausfinden, wo Sie sich ungefähr befinden"</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"Auf SurfaceFlinger zugreifen"</string>
- <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Ermöglicht einer Anwendung, die systemnahen SurfaceFlinger-Funktionen zu verwenden"</string>
+ <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Ermöglicht einer App, die systemnahen SurfaceFlinger-Funktionen zu verwenden"</string>
<string name="permlab_readFrameBuffer" msgid="6690504248178498136">"Frame-Puffer lesen"</string>
- <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Ermöglicht einer Anwendung, den Content des Frame-Puffers zu lesen"</string>
+ <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Ermöglicht einer App, den Content des Frame-Puffers zu lesen"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Audio-Einstellungen ändern"</string>
- <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Ermöglicht der Anwendung, Änderungen an allgemeinen Audioeinstellungen wie Lautstärke und Weiterleitung vorzunehmen"</string>
+ <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Ermöglicht der App, Änderungen an allgemeinen Audioeinstellungen wie Lautstärke und Weiterleitung vorzunehmen"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
- <string name="permdesc_recordAudio" msgid="6493228261176552356">"Ermöglicht der Anwendung, auf den Pfad für Audioaufzeichnungen zuzugreifen"</string>
+ <string name="permdesc_recordAudio" msgid="6493228261176552356">"Ermöglicht der App, auf den Pfad für Audioaufzeichnungen zuzugreifen"</string>
<string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
- <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der Anwendung, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder aus dem Sichtfeld der Kamera erfassen."</string>
+ <string name="permdesc_camera" msgid="6004878235852154239">"Ermöglicht der App, Fotos und Videos mit der Kamera aufzunehmen. So kann die Anwendung jederzeit Bilder aus dem Sichtfeld der Kamera erfassen."</string>
<string name="permlab_brick" product="tablet" msgid="2961292205764488304">"Tablet dauerhaft deaktivieren"</string>
<string name="permlab_brick" product="default" msgid="8337817093326370537">"Telefon dauerhaft deaktivieren"</string>
- <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ermöglicht der Anwendung, das gesamte Tablet dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
- <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Ermöglicht der Anwendung, das gesamte Telefon dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ermöglicht der App, das gesamte Tablet dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
+ <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Ermöglicht der App, das gesamte Telefon dauerhaft zu deaktivieren. Dies birgt hohe Risiken."</string>
<string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"Tablet-Neustart erzwingen"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"Neustart des Telefons erzwingen"</string>
- <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ermöglicht der Anwendung, einen Neustart des Tablets zu erzwingen."</string>
- <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Ermöglicht der Anwendung, einen Neustart des Telefons zu erzwingen"</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ermöglicht der App, einen Neustart des Tablets zu erzwingen."</string>
+ <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Ermöglicht der App, einen Neustart des Telefons zu erzwingen"</string>
<string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"Dateisysteme bereitstellen oder Bereitstellung aufheben"</string>
- <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ermöglicht der Anwendung, Dateisysteme für austauschbare Datenträger bereitzustellen oder die Bereitstellung aufzuheben"</string>
+ <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ermöglicht der App, Dateisysteme für austauschbare Datenträger bereitzustellen oder die Bereitstellung aufzuheben"</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"Externen Speicher formatieren"</string>
- <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ermöglicht der Anwendung, austauschbare Datenträger zu formatieren"</string>
+ <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ermöglicht der App, austauschbare Datenträger zu formatieren"</string>
<string name="permlab_asec_access" msgid="3411338632002193846">"Informationen zum internen Speicher abrufen"</string>
- <string name="permdesc_asec_access" msgid="8820326551687285439">"Ermöglicht der Anwendung, Informationen zum internen Speicher abzurufen."</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Ermöglicht der App, Informationen zum internen Speicher abzurufen."</string>
<string name="permlab_asec_create" msgid="6414757234789336327">"Internen Speicher erstellen"</string>
- <string name="permdesc_asec_create" msgid="2621346764995731250">"Ermöglicht der Anwendung, einen internen Speicher zu erstellen."</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Ermöglicht der App, einen internen Speicher zu erstellen."</string>
<string name="permlab_asec_destroy" msgid="526928328301618022">"Internen Speicher vernichten"</string>
- <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ermöglicht der Anwendung, den internen Speicher zu vernichten."</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ermöglicht der App, den internen Speicher zu vernichten."</string>
<string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"Internen Speicher bereitstellen/trennen"</string>
- <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ermöglicht der Anwendung, internen Speicher bereitzustellen bzw. zu trennen."</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ermöglicht der App, internen Speicher bereitzustellen bzw. zu trennen."</string>
<string name="permlab_asec_rename" msgid="7496633954080472417">"Internen Speicher umbenennen"</string>
- <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ermöglicht der Anwendung, den internen Speicher umzubenennen."</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ermöglicht der App, den internen Speicher umzubenennen."</string>
<string name="permlab_vibrate" msgid="7768356019980849603">"Vibrationsalarm steuern"</string>
- <string name="permdesc_vibrate" msgid="2886677177257789187">"Ermöglicht der Anwendung, den Vibrationsalarm zu steuern"</string>
+ <string name="permdesc_vibrate" msgid="2886677177257789187">"Ermöglicht der App, den Vibrationsalarm zu steuern"</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"Lichtanzeige steuern"</string>
- <string name="permdesc_flashlight" msgid="6433045942283802309">"Ermöglicht der Anwendung, die Lichtanzeige zu steuern"</string>
+ <string name="permdesc_flashlight" msgid="6433045942283802309">"Ermöglicht der App, die Lichtanzeige zu steuern"</string>
<string name="permlab_manageUsb" msgid="1113453430645402723">"Einstellungen und Berechtigungen für USB-Geräte verwalten"</string>
- <string name="permdesc_manageUsb" msgid="6148489202092166164">"Ermöglicht der Anwendung das Verwalten von Einstellungen und Berechtigungen für USB-Geräte"</string>
+ <string name="permdesc_manageUsb" msgid="6148489202092166164">"Ermöglicht der App das Verwalten von Einstellungen und Berechtigungen für USB-Geräte"</string>
<string name="permlab_accessMtp" msgid="4953468676795917042">"MTP-Protokoll implementieren"</string>
<string name="permdesc_accessMtp" msgid="6532961200486791570">"Erlaubt den Zugriff auf den Kernel-MTP-Treiber zur Implementierung des MTP-USB-Protokolls."</string>
<string name="permlab_hardware_test" msgid="4148290860400659146">"Hardware testen"</string>
- <string name="permdesc_hardware_test" msgid="3668894686500081699">"Ermöglicht einer Anwendung, verschiedene Peripherie-Geräte zu Hardware-Testzwecken zu steuern"</string>
+ <string name="permdesc_hardware_test" msgid="3668894686500081699">"Ermöglicht einer App, verschiedene Peripherie-Geräte zu Hardware-Testzwecken zu steuern"</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"Telefonnummern direkt anrufen"</string>
<string name="permdesc_callPhone" msgid="3369867353692722456">"Ermöglicht dem Anwendungen, Rufnummern ohne Ihr Eingreifen zu wählen. Schädliche Anwendungen können für unerwartete Anrufe auf Ihrer Telefonrechnung verantwortlich sein. Das Wählen von Notrufnummern ist allerdings nicht möglich."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"Alle Telefonnummern direkt anrufen"</string>
- <string name="permdesc_callPrivileged" msgid="244405067160028452">"Ermöglicht der Anwendung, ohne Ihr Eingreifen eine beliebige Telefonnummer zu wählen, einschließlich Notfallnummern. Schädliche Anwendungen können so unnötige und illegale Anrufe an Notdienste tätigen."</string>
+ <string name="permdesc_callPrivileged" msgid="244405067160028452">"Ermöglicht der App, ohne Ihr Eingreifen eine beliebige Telefonnummer zu wählen, einschließlich Notfallnummern. Schädliche Anwendungen können so unnötige und illegale Anrufe an Notdienste tätigen."</string>
<string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"CDMA-Tablet-Einrichtung direkt starten"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA-Telefoneinrichtung direkt starten"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Der Anwendung wird der Start der CDMA-Bereitstellung ermöglicht. Schädliche Anwendungen können die CDMA-Bereitstellung unnötigerweise starten."</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"Benachrichtigungen für Standortaktualisierung steuern"</string>
- <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Ermöglicht die Aktivierung/Deaktivierung der Mobilfunkbenachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Ermöglicht die Aktivierung/Deaktivierung der Mobilfunkbenachrichtigungen über Standort-Updates. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_checkinProperties" msgid="7855259461268734914">"Auf Check-In-Eigenschaften zugreifen"</string>
- <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_bindGadget" msgid="776905339015863471">"Widgets auswählen"</string>
- <string name="permdesc_bindGadget" msgid="2098697834497452046">"Ermöglicht der Anwendung, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_bindGadget" msgid="2098697834497452046">"Ermöglicht der App, dem System zu melden, welche Widgets von welcher Anwendung verwendet werden können. Mit dieser Berechtigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten gewähren. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"Telefonstatus ändern"</string>
- <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
+ <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ermöglicht einer App, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder die Mobilfunkverbindung des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"Telefonstatus lesen und identifizieren"</string>
- <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der Anwendung, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
+ <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ermöglicht der App, auf die Telefonfunktionen des Gerätes zuzugreifen. Eine Anwendung mit dieser Berechtigung kann unter anderem bestimmen, welche Telefonnummer dieses Telefon verwendet, ob ein Anruf aktiv ist oder mit welcher Nummer der Anrufer verbunden ist."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"Standby-Modus des Tablets deaktivieren"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Standby-Modus deaktivieren"</string>
- <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ermöglicht einer Anwendung, den Standby-Modus des Tablets zu deaktivieren."</string>
- <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Ermöglicht einer Anwendung, den Standby-Modus des Telefons zu deaktivieren"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ermöglicht einer App, den Standby-Modus des Tablets zu deaktivieren."</string>
+ <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Ermöglicht einer App, den Standby-Modus des Telefons zu deaktivieren"</string>
<string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"Tablet ein- oder ausschalten"</string>
<string name="permlab_devicePower" product="default" msgid="4928622470980943206">"Gerät ein- oder ausschalten"</string>
- <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ermöglicht der Anwendung, das Tablet ein- oder auszuschalten."</string>
- <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Ermöglicht der Anwendung, das Telefon ein- oder auszuschalten"</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ermöglicht der App, das Tablet ein- oder auszuschalten."</string>
+ <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Ermöglicht der App, das Telefon ein- oder auszuschalten"</string>
<string name="permlab_factoryTest" msgid="3715225492696416187">"In Werkstestmodus ausführen"</string>
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Tablet-Hardware zugegriffen werden kann. Nur verfügbar, wenn ein Tablet im Herstellertestmodus ausgeführt wird."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Führt einen systemnahen Herstellertest durch, in dessen Rahmen auf die gesamte Telefon-Hardware zugegriffen werden kann. Nur verfügbar, wenn ein Telefon im Herstellertestmodus ausgeführt wird."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"Hintergrund festlegen"</string>
- <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ermöglicht der Anwendung, den System-Hintergrund festzulegen"</string>
+ <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ermöglicht der App, den System-Hintergrund festzulegen"</string>
<string name="permlab_setWallpaperHints" msgid="3600721069353106851">"Größenhinweise für Hintergrund festlegen"</string>
- <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Ermöglicht der Anwendung, die Größenhinweise für den Hintergrund festzulegen"</string>
+ <string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Ermöglicht der App, die Größenhinweise für den Hintergrund festzulegen"</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"System auf Werkseinstellung zurücksetzen"</string>
- <string name="permdesc_masterClear" msgid="5033465107545174514">"Ermöglicht einer Anwendung, das System komplett auf Werkseinstellung zurückzusetzen. Hierbei werden alle Daten, Konfigurationen und installierten Anwendungen gelöscht."</string>
+ <string name="permdesc_masterClear" msgid="5033465107545174514">"Ermöglicht einer App, das System komplett auf Werkseinstellung zurückzusetzen. Hierbei werden alle Daten, Konfigurationen und installierten Anwendungen gelöscht."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"Zeit einstellen"</string>
- <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Ermöglicht einer Anwendung, die Uhrzeit des Tablets zu ändern"</string>
- <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Ermöglicht einer Anwendung, die Uhrzeit des Telefons zu ändern"</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Ermöglicht einer App, die Uhrzeit des Tablets zu ändern"</string>
+ <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Ermöglicht einer App, die Uhrzeit des Telefons zu ändern"</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"Zeitzone festlegen"</string>
- <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Ermöglicht einer Anwendung, die Zeitzone des Tablets zu ändern."</string>
- <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Ermöglicht einer Anwendung, die Zeitzone des Telefons zu ändern"</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Ermöglicht einer App, die Zeitzone des Tablets zu ändern."</string>
+ <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Ermöglicht einer App, die Zeitzone des Telefons zu ändern"</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"Als Konto-Manager fungieren"</string>
- <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Ermöglicht einer Anwendung, Anrufe an Konto-Authentifizierer zu tätigen"</string>
+ <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Ermöglicht einer App, Anrufe an Konto-Authentifizierer zu tätigen"</string>
<string name="permlab_getAccounts" msgid="4549918644233460103">"bekannte Konten suchen"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ermöglicht einer Anwendung, eine Liste der dem Tablet bekannten Konten abzurufen."</string>
- <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Ermöglicht einer Anwendung, eine Liste der dem Telefon bekannten Konten abzurufen"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ermöglicht einer App, eine Liste der dem Tablet bekannten Konten abzurufen."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Ermöglicht einer App, eine Liste der dem Telefon bekannten Konten abzurufen"</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"Als Kontoauthentifizierer fungieren"</string>
- <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Ermöglicht einer Anwendung, die Kontoauthentifizierungsfunktionen des Konto-Managers zu verwenden, einschließlich die Funktionen zum Erstellen von Konten und zum Abrufen und Einstellen der entsprechenden Passwörter"</string>
+ <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Ermöglicht einer App, die Kontoauthentifizierungsfunktionen des Konto-Managers zu verwenden, einschließlich die Funktionen zum Erstellen von Konten und zum Abrufen und Einstellen der entsprechenden Passwörter"</string>
<string name="permlab_manageAccounts" msgid="4440380488312204365">"Kontoliste verwalten"</string>
- <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Ermöglicht einer Anwendung, Konten hinzuzufügen und zu entfernen oder deren Passwörter zu löschen"</string>
+ <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Ermöglicht einer App, Konten hinzuzufügen und zu entfernen oder deren Passwörter zu löschen"</string>
<string name="permlab_useCredentials" msgid="6401886092818819856">"Authentifizierungsinformationen eines Kontos verwenden"</string>
- <string name="permdesc_useCredentials" msgid="7416570544619546974">"Ermöglicht einer Anwendung, Authentifizierungs-Token anzufordern"</string>
+ <string name="permdesc_useCredentials" msgid="7416570544619546974">"Ermöglicht einer App, Authentifizierungs-Token anzufordern"</string>
<string name="permlab_accessNetworkState" msgid="6865575199464405769">"Netzwerkstatus anzeigen"</string>
- <string name="permdesc_accessNetworkState" msgid="558721128707712766">"Ermöglicht einer Anwendung, den Status aller Netzwerke anzuzeigen"</string>
+ <string name="permdesc_accessNetworkState" msgid="558721128707712766">"Ermöglicht einer App, den Status aller Netzwerke anzuzeigen"</string>
<string name="permlab_createNetworkSockets" msgid="9121633680349549585">"uneingeschränkter Internetzugriff"</string>
- <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"Ermöglicht einer Anwendung, Netzwerk-Sockets einzurichten"</string>
+ <string name="permdesc_createNetworkSockets" msgid="4593339106921772192">"Ermöglicht einer App, Netzwerk-Sockets einzurichten"</string>
<string name="permlab_writeApnSettings" msgid="7823599210086622545">"Einstellungen für Zugriffspunktname schreiben"</string>
- <string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Ermöglicht einer Anwendung, die APN-Einstellungen wie Proxy und Port eines Zugriffspunkts zu ändern"</string>
+ <string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Ermöglicht einer App, die APN-Einstellungen wie Proxy und Port eines Zugriffspunkts zu ändern"</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"Netzwerkkonnektivität ändern"</string>
- <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Ermöglicht einer Anwendung, den Status der Netzwerkkonnektivität zu ändern"</string>
+ <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Ermöglicht einer App, den Status der Netzwerkkonnektivität zu ändern"</string>
<string name="permlab_changeTetherState" msgid="2702121155761140799">"Tethering-Konnektivität ändern"</string>
- <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Ermöglicht einer Anwendung, den Status der Tethering-Konnektivität zu ändern"</string>
+ <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Ermöglicht einer App, den Status der Tethering-Konnektivität zu ändern"</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"Einstellung zur Verwendung von Hintergrunddaten ändern"</string>
- <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Ermöglicht einer Anwendung, die Einstellung der Verwendung von Hintergrunddaten zu ändern"</string>
+ <string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Ermöglicht einer App, die Einstellung der Verwendung von Hintergrunddaten zu ändern"</string>
<string name="permlab_accessWifiState" msgid="8100926650211034400">"WLAN-Status anzeigen"</string>
- <string name="permdesc_accessWifiState" msgid="485796529139236346">"Ermöglicht einer Anwendung, die Informationen zum WLAN-Status einzusehen"</string>
+ <string name="permdesc_accessWifiState" msgid="485796529139236346">"Ermöglicht einer App, die Informationen zum WLAN-Status einzusehen"</string>
<string name="permlab_changeWifiState" msgid="7280632711057112137">"WLAN-Status ändern"</string>
- <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Ermöglicht einer Anwendung, eine Verbindung zu den WLAN-Zugangspunkten herzustellen und diese zu trennen oder Änderungen an den konfigurierten WLAN-Netzwerken vorzunehmen"</string>
+ <string name="permdesc_changeWifiState" msgid="2950383153656873267">"Ermöglicht einer App, eine Verbindung zu den WLAN-Zugangspunkten herzustellen und diese zu trennen oder Änderungen an den konfigurierten WLAN-Netzwerken vorzunehmen"</string>
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"WLAN-Multicast-Empfang zulassen"</string>
- <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ermöglicht einer Anwendung, Datenpakete zu empfangen, die nicht direkt an Ihr Gerät gerichtet sind. Dies kann bei der Erkennung von in der Nähe angebotenen Diensten hilfreich sein. Diese Einstellung verbraucht mehr Energie als der Nicht-Multicast-Modus."</string>
+ <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ermöglicht einer App, Datenpakete zu empfangen, die nicht direkt an Ihr Gerät gerichtet sind. Dies kann bei der Erkennung von in der Nähe angebotenen Diensten hilfreich sein. Diese Einstellung verbraucht mehr Energie als der Nicht-Multicast-Modus."</string>
<string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"Bluetooth-Verwaltung"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ermöglicht einer Anwendung, das lokale Bluetooth-Tablet zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Ermöglicht einer Anwendung, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ermöglicht einer App, das lokale Bluetooth-Tablet zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Ermöglicht einer App, das lokale Bluetooth-Telefon zu konfigurieren, Remote-Geräte zu erkennen und eine Verbindung zu diesen herzustellen"</string>
<string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth-Verbindungen herstellen"</string>
- <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Tablets einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
- <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren"</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ermöglicht einer App, die Konfiguration des lokalen Bluetooth-Tablets einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
+ <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ermöglicht einer App, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren"</string>
<string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
- <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer Anwendung die Kommunikation mit Tags für Nahfeldkommunikation, Karten und Lesegeräte"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer App die Kommunikation mit Tags für Nahfeldkommunikation, Karten und Lesegeräte"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"Gesamten Netzwerkverkehr abfangen und ändern"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Ermöglicht einer App, den gesamten Netzwerkverkehr, etwa zum Aufbau einer VPN-Verbindung, abzufangen und zu überprüfen. Schädliche Apps können so Netzwerkpakete ohne Ihr Wissen überwachen, weiterleiten oder ändern."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Ermöglicht einer App, den gesamten Netzwerkverkehr zum Aufbau einer VPN-Verbindung abzufangen und zu überprüfen. Schädliche Apps können Netzwerkpakete ohne Ihr Wissen überwachen, weiterleiten oder ändern."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"Tastensperre deaktivieren"</string>
- <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer Anwendung, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
+ <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer App, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
- <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Ermöglicht einer Anwendung, die Synchronisierungseinstellungen zu lesen, etwa ob die Synchronisierung für Kontakte aktiviert ist oder nicht"</string>
+ <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Ermöglicht einer App, die Synchronisierungseinstellungen zu lesen, etwa ob die Synchronisierung für Kontakte aktiviert ist oder nicht"</string>
<string name="permlab_writeSyncSettings" msgid="6297138566442486462">"Synchronisierungseinstellungen schreiben"</string>
- <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Ermöglicht einer Anwendung, die Synchronisierungseinstellungen zu ändern, etwa ob die Synchronisierung für Kontakte aktiviert ist oder nicht"</string>
+ <string name="permdesc_writeSyncSettings" msgid="2498201614431360044">"Ermöglicht einer App, die Synchronisierungseinstellungen zu ändern, etwa ob die Synchronisierung für Kontakte aktiviert ist oder nicht"</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"Synchronisierungsstatistiken lesen"</string>
- <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Ermöglicht einer Anwendung, die Synchronisierungsstatistiken zu lesen, etwa den Verlauf der bereits durchgeführten Synchronisierungen"</string>
+ <string name="permdesc_readSyncStats" msgid="7511448343374465000">"Ermöglicht einer App, die Synchronisierungsstatistiken zu lesen, etwa den Verlauf der bereits durchgeführten Synchronisierungen"</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"abonnierte Feeds lesen"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Ermöglicht einer Anwendung, Details zu den zurzeit synchronisierten Feeds abzurufen"</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="3622200625634207660">"Ermöglicht einer App, Details zu den zurzeit synchronisierten Feeds abzurufen"</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"abonnierte Feeds schreiben"</string>
- <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."</string>
+ <string name="permdesc_subscribedFeedsWrite" msgid="8121607099326533878">"Ermöglicht einer App, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."</string>
<string name="permlab_readDictionary" msgid="432535716804748781">"nutzerdefiniertes Wörterbuch lesen"</string>
- <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ermöglicht einer Anwendung, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat"</string>
+ <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ermöglicht einer App, alle privaten Wörter, Namen und Ausdrücke zu lesen, die ein Nutzer in seinem Wörterbuch gespeichert hat"</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"in nutzerdefiniertes Wörterbuch schreiben"</string>
- <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer Anwendung, Ihrem Wörterbuch neue Einträge hinzuzufügen"</string>
+ <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ermöglicht einer App, Ihrem Wörterbuch neue Einträge hinzuzufügen"</string>
<string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB-Speicherinhalt ändern/löschen"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"SD-Karten-Inhalt ändern/löschen"</string>
- <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ermöglicht der Anwendung Schreiben in USB-Speicher"</string>
- <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ermöglicht der App Schreiben in USB-Speicher"</string>
+ <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer App, auf die SD-Karte zu schreiben"</string>
<string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Intern. Mediensp. änd./löschen"</string>
- <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ermöglicht einer Anwendung, den Inhalt des internen Medienspeichers zu ändern"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ermöglicht einer App, den Inhalt des internen Medienspeichers zu ändern"</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"Zugriff auf das Cache-Dateisystem"</string>
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Gewährt einer Anwendung Lese- und Schreibzugriff auf das Cache-Dateisystem."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"Internetanrufe tätigen/annehmen"</string>
- <string name="permdesc_use_sip" msgid="6320376185606661843">"Ermöglicht einer Anwendung die Verwendung des SIP-Dienstes zum Tätigen/Annehmen von Internetanrufen"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Ermöglicht einer App die Verwendung des SIP-Dienstes zum Tätigen/Annehmen von Internetanrufen"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Displays festlegen"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Legen Sie fest, wie häufig das Passwort zum Sperren des Bildschirms geändert werden muss."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Speicherverschlüsselung"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Anforderung, dass gespeicherte Anwendungsdaten verschlüsselt werden"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Privat"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Geschäftlich"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Sonstige"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-Code eingeben"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"PUK und neuen PIN-Code eingeben"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-Code"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Neuer PIN-Code"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Zum Eingeben des Passworts berühren"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Passwort zum Entsperren eingeben"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"PIN zum Entsperren eingeben"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Keine SIM-Karte im Telefon"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Bitte legen Sie eine SIM-Karte ein."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Nur Notrufe"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netzwerk gesperrt"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"PUK-Sperre auf SIM"</string>
@@ -682,14 +712,14 @@
<string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
<string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Browserverlauf und Lesezeichen lesen"</string>
- <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der Anwendung, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen"</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ermöglicht der App, alle URLs, die mit dem Browser besucht wurden, sowie alle Lesezeichen des Browsers zu lesen"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Browserverlauf und Lesezeichen schreiben"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ermöglicht einer Anwendung, den auf Ihrem Tablet gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ermöglicht einer Anwendung, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ermöglicht einer App, den auf Ihrem Tablet gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ermöglicht einer App, den auf Ihrem Telefon gespeicherten Browserverlauf und die Lesezeichen zu ändern. Schädliche Anwendungen können so Ihre Browserdaten löschen oder ändern."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"Alarm im Wecker festlegen"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Ermöglicht dieser Anwendung, einen Alarm mithilfe eines installierten Weckers festzulegen. Einige Weckeranwendungen verfügen möglicherweise nicht über diese Funktion."</string>
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolokalisierungsberechtigungen des Browsers ändern"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ermöglicht einer Anwendung, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Anwendungen können dies nutzen, um das Senden von Standortinformationen an willkürliche Websites zuzulassen."</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ermöglicht einer App, die Geolokalisierungsberechtigungen des Browsers zu ändern. Schädliche Anwendungen können dies nutzen, um das Senden von Standortinformationen an willkürliche Websites zuzulassen."</string>
<string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nicht jetzt"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Speichern"</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Wenn Sie den USB-Speicher aktivieren, werden einige von Ihnen verwendete Anwendungen angehalten und sind möglicherweise nicht verfügbar, bis Sie den USB-Speicher wieder deaktivieren."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-Vorgang fehlgeschlagen"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-Sp. formatieren"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-Karte formatieren"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-Speicher formatieren und alle darin befindlichen Dateien löschen? Diese Aktion kann nicht rückgängig gemacht werden!"</string>
@@ -961,7 +995,7 @@
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-Karte entfernt. Neue Karte einlegen"</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Keine passenden Aktivitäten gefunden"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"Nutzungsstatistik der Komponente aktualisieren"</string>
- <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Anwendungen vorgesehen."</string>
+ <string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Ermöglicht die Änderung von gesammelten Nutzungsstatistiken der Komponente. Nicht für normale Apps vorgesehen."</string>
<string name="permlab_copyProtectedData" msgid="1660908117394854464">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Nicht zum Gebrauch mit normalen Anwendungen."</string>
<string name="permdesc_copyProtectedData" msgid="537780957633976401">"Ermöglicht das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalt. Nicht zum Gebrauch mit normalen Anwendungen."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Für Zoomeinstellung zweimal berühren"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer-2-Tunneling-Protokoll"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec-VPN mit vorinstalliertem Schlüssel"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec-VPN mit Zertifikat"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Keine ausgewählt"</string>
<string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
@@ -1020,11 +1062,11 @@
<string name="format_error" product="nosdcard" msgid="4320339096529911637">"USB-Speicher konnte nicht gelöscht werden."</string>
<string name="format_error" product="default" msgid="1343380371925238343">"SD-Karte konnte nicht gelöscht werden."</string>
<string name="media_bad_removal" msgid="7960864061016603281">"SD-Karte wurde vor dem Trennvorgang entfernt."</string>
- <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Der USB-Speicher wird derzeit überprüft."</string>
- <string name="media_checking" product="default" msgid="7334762503904827481">"Die SD-Karte wird derzeit überprüft."</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Der USB-Speicher wird zurzeit überprüft."</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"Die SD-Karte wird zurzeit überprüft."</string>
<string name="media_removed" msgid="7001526905057952097">"Die SD-Karte wurde entfernt."</string>
- <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Der USB-Speicher wird derzeit von einem Computer verwendet."</string>
- <string name="media_shared" product="default" msgid="5706130568133540435">"Die SD-Karte wird derzeit von einem Computer verwendet."</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Der USB-Speicher wird zurzeit von einem Computer verwendet."</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"Die SD-Karte wird zurzeit von einem Computer verwendet."</string>
<string name="media_unknown_state" msgid="729192782197290385">"Unbekannter Status des externen Speichermediums"</string>
<string name="share" msgid="1778686618230011964">"Weitergeben"</string>
<string name="find" msgid="4808270900322985960">"Suchen"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Interner Speicher"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-Karte"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-Speicher"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Bearbeiten..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Sicherheitszertifikat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dies ist ein gültiges Zertifikat."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Ausgegeben an:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Allgemeiner Name."</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisationseinheit:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Ausgegeben von:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Gültigkeit:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Ausgegeben am:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Läuft ab am:"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a5e13f1..81b9107 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Ο κωδικός PUK που πληκτρολογήσατε είναι εσφαλμένος."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Οι αριθμοί PIN που πληκτρολογήσατε δεν ταιριάζουν."</string>
<string name="invalidPin" msgid="3850018445187475377">"Πληκτρολογήστε έναν αριθμό PIN μεγέθους 4 έως 8 αριθμών."</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="ClipMmi" msgid="6952821216480289285">"Εισερχόμενη αναγνώριση κλήσης"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Λειτουργία πτήσης"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Η λειτουργία πτήσης είναι ενεργοποιημένη."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Η λειτουργία πτήσης είναι απενεργοποιημένη"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
<string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Υπηρεσίες επί πληρωμή"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Επιτρέπει σε μια εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων SMS. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να σας ειδοποιούν."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"λήψη MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Επιτρέπει σε μια εφαρμογή την λήψη και την επεξεργασία μηνυμάτων MMS. Κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν τα μηνύματά σας ή να τα διαγράφουν χωρίς να σας ειδοποιούν."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"λαμβάνει τις μεταδόσεις σε περιπτώσεις έκτακτης ανάγκης"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Επιτρέπει σε μια εφαρμογή να κάνει λήψη και επεξεργασία μηνυμάτων από μεταδόσεις σε περιπτώσεις έκτακτης ανάγκης. Αυτή η άδεια είναι διαθέσιμη μόνο σε εφαρμογές συστήματος."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"αποστολή μηνυμάτων SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Επιτρέπει σε μια εφαρμογή την αποστολή μηνυμάτων SMS. Κακόβουλες εφαρμογές ενδέχεται να σας χρεώσουν αποστέλλοντας μηνύματα χωρίς την έγκρισή σας."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"ανάγνωση μηνυμάτων SMS ή MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Επιτρέπει σε μια εφαρμογή να εξαναγκάσει οποιαδήποτε δραστηριότητα που βρίσκεται στο προσκήνιο να κλείσει και να μεταβεί στο φόντο. Δεν είναι απαραίτητο για κανονικές εφαρμογές."</string>
<string name="permlab_dump" msgid="1681799862438954752">"ανάκτηση εσωτερικής κατάστασης συστήματος"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Επιτρέπει σε μια εφαρμογή να ανακτήσει την εσωτερική κατάσταση του συστήματος. Κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν μεγάλο εύρος ιδιωτικών και ασφαλών πληροφοριών, τις οποίες δεν χρειάζονται."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ανάκτηση περιεχομένου οθόνης"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Επιτρέπει σε μια εφαρμογή την ανάκτηση του περιεχομένου του ενεργού παραθύρου. Οι κακόβουλες εφαρμογές ενδέχεται να κάνουν ανάκτηση ολόκληρου του περιεχομένου του παραθύρου και να εξετάσουν ολόκληρο το κείμενό του, εκτός από τους κωδικούς πρόσβασης."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν θα χρειαστεί ποτέ για κανονικές εφαρμογές."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"αλλαγή προσανατολισμού οθόνης"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Επιτρέπει σε μια εφαρμογή την αλλαγή της περιστροφής της οθόνης οποιαδήποτε στιγμή. Δεν είναι απαραίτητο για κανονικές εφαρμογές."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"αλλαγή ταχύτητας δείκτη"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Επιτρέπει σε μια εφαρμογή την αλλαγή της ταχύτητας του δείκτη του ποντικιού ή της επιφάνειας αφής ανά πάσα στιγμή. Υπό κανονικές συνθήκες, δεν απαιτείται για κανονικές εφαρμογές."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"αποστολή σημάτων Linux σε εφαρμογές"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Επιτρέπει σε μια εφαρμογή την αποστολή αιτήματος για την αποστολή του παρεχόμενου σήματος σε όλες τις υπάρχουσες διαδικασίες."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"η εφαρμογή να εκτελείται συνεχώς"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"εγγραφή δεδομένων επαφής"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα επαφής (διεύθυνσης) που είναι αποθηκευμένα στο tablet σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα επαφών σας."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Επιτρέπει σε μια εφαρμογή να τροποποιεί τα δεδομένα επαφής (διεύθυνσης) που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα επαφών σας."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"ανάγνωση συμβάντων ημερολογίου"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Επιτρέπει σε μια εφαρμογή να αναγνώσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο tablet σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν συμβάντα ημερολογίου σε άλλους χρήστες."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Επιτρέπει σε μια εφαρμογή να αναγνώσει όλα τα συμβάντα ημερολογίου που είναι αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να αποστείλουν συμβάντα ημερολογίου σε άλλους χρήστες."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"έλεγχος Επικοινωνίας κοντινού πεδίου (Near Field Communication)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Επιτρέπει σε μια εφαρμογή την επικοινωνία με ετικέτες, τις κάρτες και τους αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"παρακολούθηση και τροποποίηση όλης της επισκεψιμότητας δικτύου"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Επιτρέπει σε μια εφαρμογή να παρακολουθεί και να επιθεωρεί το σύνολο της επισκεψιμότητας του δικτύου, για παράδειγμα για τη δημιουργία μιας σύνδεσης VPN. Οι κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν, να ανακατευθύνουν ή να τροποποιούν τα πακέτα δικτύου χωρίς να το γνωρίζετε."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Επιτρέπει σε μια εφαρμογή να παρακολουθεί και να επιθεωρεί το σύνολο της επισκεψιμότητας του δικτύου, για παράδειγμα, για τη δημιουργία σύνδεσης VPN. Οι κακόβουλες εφαρμογές ενδέχεται να παρακολουθούν, να ανακατευθύνουν ή να τροποποιούν τα πακέτα δικτύου χωρίς να το γνωρίζετε."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"απενεργοποίηση κλειδώματος πληκτρολογίου"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Επιτρέπει σε μια εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, η απενεργοποίηση του κλειδώματος πληκτρολογίου όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και η επανενεργοποίηση του κλειδώματος πληκτρολογίου όταν η κλήση τερματιστεί."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Επιτρέπει σε μια εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Επιτρέπει σε μια εφαρμογή τη χρήση της υπηρεσίας SIP για την πραγματοποίηση/λήψη κλήσεων μέσω Διαδικτύου."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Επιλέξτε πόσο συχνά θα πρέπει να αλλάζει ο κωδικός πρόσβασης κλειδώματος οθόνης"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ορισμός κρυπτογρ. αποθ. χώρου"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Να απαιτείται η κρυπτογράφηση των αποθηκευμένων δεδομένων εφαρμογής"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Οικία"</item>
<item msgid="869923650527136615">"Κινητό"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Εργασία"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Άλλο"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Πληκτρολογήστε τον κωδικό αριθμό PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Καταχωρήστε τον κωδικό PUK και τον νέο κωδικό PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Κωδικός PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Νέος κωδικός PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Αγγίξτε για εισαγ. κωδ."</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Εισαγάγετε τον κωδικό πρόσβασης για ξεκλείδωμα"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Εισαγάγετε το PIN για ξεκλείδωμα"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Δεν υπάρχει κάρτα SIM στο τηλέφωνο."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Τοποθετήστε μια κάρτα SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Εάν ενεργοποιήσετε τον αποθηκευτικό χώρο USB, ορισμένες από τις εφαρμογές που χρησιμοποιείτε θα σταματήσουν και ενδέχεται να μην είναι διαθέσιμες μέχρι να απενεργοποιήσετε τον αποθηκευτικό χώρο USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Απέτυχε η λειτουργία USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"ΟΚ"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Να γίνει διαγραφή του αποθηκευτικού χώρου USB, η οποία θα διαγράψει όλα τα αρχεία που έχετε αποθηκεύσει εκεί; Η ενέργεια είναι μη αναστρέψιμη!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Πρωτόκολλο Layer 2 Tunneling Protocol (L2TP)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Κλειδί pre-shared βάσει L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Πιστοποιητικό βάσει L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
<string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Εσωτερικός χώρος αποθήκευσης"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Κάρτα SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Χώρος αποθήκευσης USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Επεξεργασία..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Πιστοποιητικό ασφαλείας"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Αυτό το πιστοποιητικό είναι έγκυρο."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Εκδόθηκε στις:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Κοινό όνομα:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Οργανισμός:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Μονάδα οργάνωσης:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Εκδόθηκε:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Ισχύς:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Εκδόθηκε στις:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Λήγει:"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d5ef98b..903e75f 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"The PUK that you typed is not correct."</string>
<string name="mismatchPin" msgid="3695902225843339274">"The PINs that you entered do not match."</string>
<string name="invalidPin" msgid="3850018445187475377">"Type a PIN that is 4 to 8 numbers."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Type a PUK that is 8 numbers or longer."</string>
<string name="needPuk" msgid="919668385956251611">"Your SIM card is PUK-locked. Type the PUK code to unlock it."</string>
<string name="needPuk2" msgid="4526033371987193070">"Type PUK2 to unblock SIM card."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Incoming Caller ID"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aiplane mode is ON"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Airplane mode is OFF"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"receive MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"receive emergency broadcasts"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Allows application to receive and process emergency broadcast messages. This permission is only available to system applications."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"send SMS messages"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"read SMS or MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications."</string>
<string name="permlab_dump" msgid="1681799862438954752">"retrieve system internal status"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Allows application to retrieve internal status of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"retrieve screen content"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Allows application to retrieve the content of the active window. Malicious applications may retrieve the entire window content and examine all its text, except passwords."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Allows the holder to send intents to a device administrator. Should never be needed for normal applications."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"change pointer speed"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Allows an application to change the mouse or track pad pointer speed at any time. Should never be needed for normal applications."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"send Linux signals to applications"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Allows application to request that the supplied signal be sent to all persistent processes."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"make application always run"</string>
@@ -316,6 +319,10 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"write contact data"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Allows an application to modify the contact (address) data stored on your tablet. Malicious applications can use this to erase or modify your contact data."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data."</string>
+ <string name="permlab_readProfile" msgid="2211941946684590103">"read profile data"</string>
+ <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Allows an application to read all of your personal profile information. Malicious applications can use this to identify you and send your personal information to other people."</string>
+ <string name="permlab_writeProfile" msgid="6561668046361989220">"write profile data"</string>
+ <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Allows an application to modify your personal profile information. Malicious applications can use this to erase or modify your profile data."</string>
<string name="permlab_readCalendar" msgid="6898987798303840534">"read calendar events"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Allows an application to read all of the calendar events stored on your tablet. Malicious applications can use this to send your calendar events to other people."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people."</string>
@@ -453,7 +460,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"control Near-Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"intercept and modify all network traffic"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Allows an application to intercept and inspect all network traffic, for example to establish a VPN connection. Malicious applications may monitor, redirect or modify network packets without your knowledge."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Allows an application to intercept and inspect all network traffic to establish a VPN connection. Malicious applications may monitor, redirect or modify network packets without your knowledge."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"disable key lock"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"read sync settings"</string>
@@ -480,6 +487,10 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Allows an application to read and write the cache file system."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"make/receive Internet calls"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Allows an application to use the SIP service to make/receive Internet calls."</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"read historical network usage"</string>
+ <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Allows an application to read historical network usage for specific networks and applications."</string>
+ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"manage network policy"</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Allows an application to manage network policies and define application-specific rules."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Control the length and the characters allowed in screen-unlock passwords"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -498,6 +509,8 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Control how frequently the lock-screen password must be changed"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Set storage encryption"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Require that stored application data be encrypted"</string>
+ <string name="policylab_disableCamera" msgid="6395301023152297826">"Disable cameras"</string>
+ <string name="policydesc_disableCamera" msgid="5680054212889413366">"Prevent use of all device cameras"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Home"</item>
<item msgid="869923650527136615">"Mobile"</item>
@@ -612,6 +625,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Work"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Other"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Enter PIN code"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Enter PUK and new PIN code"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK code"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"New PIN Code"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Touch to enter password"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Enter password to unlock"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Enter PIN to unlock"</string>
@@ -636,6 +652,8 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No SIM card in tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No SIM card in phone."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Please insert a SIM card."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"The SIM card is missing or not readable. Please insert a SIM card."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Your SIM card is permanently disabled."\n" Please contact your wireless service provider to obtain another SIM card."</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Emergency calls only"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Network locked"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM card is PUK-locked."</string>
@@ -924,6 +942,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"If you turn on USB storage, some applications that you are using will stop and may be unavailable until you turn off USB storage."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB operation failed"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format USB storage"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format SD card"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format USB storage, erasing all files stored there? Action cannot be reversed!"</string>
@@ -991,6 +1013,10 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunnelling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Pre-shared key-based L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificate-based L2TP/IPSec VPN"</string>
+ <string name="vpn_ticker" msgid="285642105845608311">"<xliff:g id="APP">%s</xliff:g> is activating VPN..."</string>
+ <string name="vpn_title" msgid="5434034606697234123">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
+ <string name="vpn_text" msgid="1610714069627824309">"Tap to manage the network."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string>
<string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
<string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1051,6 +1077,11 @@
<string name="storage_internal" msgid="7556050805474115618">"Internal Storage"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD Card"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
- <skip />
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Edit..."</string>
+ <string name="data_usage_warning_title" msgid="1955638862122232342">"Data usage warning"</string>
+ <string name="data_usage_warning_body" msgid="3354394590936526648">"usage exceeds <xliff:g id="SIZE">%s</xliff:g>"</string>
+ <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G data disabled"</string>
+ <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G data disabled"</string>
+ <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobile data disabled"</string>
+ <string name="data_usage_limit_body" msgid="2182247539226163759">"Tap to enable"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3cb61e4..e28bd25 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"La PUK que escribiste no es correcta."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Los PIN que has ingresado no coinciden."</string>
<string name="invalidPin" msgid="3850018445187475377">"Escribir un PIN que contenga entre 4 y 8 números."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Ingresa un código PUK de ocho números o más."</string>
<string name="needPuk" msgid="919668385956251611">"Tu tarjeta SIM está bloqueada con PUK. Escribe el código PUK para desbloquearla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Escribir PUK2 para desbloquear la tarjeta SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identificador de llamadas entrantes"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"El modo avión está Encendido"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"El modo avión está Apagado"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios que te cuestan dinero"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Admite que la aplicación reciba y procese mensajes SMS. Es posible que las aplicaciones maliciosas controlen tus mensajes o los eliminen sin mostrártelos."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"recibir MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Admite que la aplicación reciba y procese mensajes MMS. Es posible que las aplicaciones maliciosas controlen tus mensajes o los eliminen sin mostrártelos."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"recibir mensajes de emergencia"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permite que una aplicación reciba y procese mensajes de emergencia. Este permiso solo está disponible para las aplicaciones del sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar mensajes SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Admite que la aplicación envíe mensajes SMS. Las aplicaciones maliciosas te pueden costar dinero si envías mensajes sin su confirmación."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"leer SMS o MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Admite una aplicación que provoca que cualquier actividad del fondo se acerque y vuelva a alejarse. Se debe evitar utilizarlo en aplicaciones normales."</string>
<string name="permlab_dump" msgid="1681799862438954752">"recuperar el estado interno del sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Admite que la aplicación recupere el estado interno del sistema. Las aplicaciones maliciosas pueden recuperar una gran variedad de información privada y segura que normalmente nunca necesitaría."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permite que una aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto excepto las contraseñas."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Pone al administrador de la actividad en estado de cierre. No realiza un cierre completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite que el propietario envíe sus intentos a un administrador de dispositivos. No se necesita para las aplicaciones normales."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar la orientación de la pantalla"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Admite una aplicación que cambia la rotación de la pantalla en cualquier momento. Se debe evitar utilizarlo en aplicaciones normales."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permite que una aplicación modifique la velocidad del puntero del mouse o del trackpad en cualquier momento. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"enviar señales de Linux a las aplicaciones"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Admite que la aplicación solicite el envío de la señal suministrada a todos los procesos continuos."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"hacer que siempre se ejecute la aplicación"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de (dirección) guardados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"Leer eventos del calendario"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en tu tablet. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Admite que una aplicación lea todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlar la Transmisión de datos en proximidad"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite que una aplicación se comunique con etiquetas, tarjetas y lectores de Transmisión de datos en proximidad (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"Interceptar y modificar todo el tráfico de red"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permite que una aplicación intercepte e inspeccione todo el tráfico de red para, por ejemplo, establecer una conexión VPN. Las aplicaciones maliciosas pueden monitorear, redireccionar o modificar paquetes de red sin que lo sepas."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permite que una aplicación intercepte e inspeccione todo el tráfico de red para establecer una conexión VPN. Las aplicaciones maliciosas pueden monitorear, redireccionar o modificar paquetes de red sin que lo sepas."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueo"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Admite una aplicación que desactiva el bloqueo y cualquier seguridad con contraseña relacionada. Un ejemplo legítimo de esto es el bloqueo desactivado por el teléfono cuando recibe una llamada telefónica entrante, y luego la reactivación del bloqueo cuando finaliza la llamada."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos caché."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"realizar o recibir llamadas por Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas por Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar cuán a menudo se debe cambiar la contraseña de bloqueo de pantalla"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Establecer la encriptación del almacenamiento"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requiere que los datos almacenados de la aplicación estén encriptados"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Casa"</item>
<item msgid="869923650527136615">"Celular"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ingresar el código de PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Ingresa el código PUK y un nuevo código PIN."</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nuevo código PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Toca para ingresar la contraseña"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ingresar la contraseña para desbloquear"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ingresa el PIN para desbloquear"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No hay tarjeta SIM en el teléfono."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Sólo llamadas de emergencia"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Red bloqueada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La tarjeta SIM está bloqueada con PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, algunas aplicaciones que estás usando se detendrán y es posible que no estén disponibles hasta que desactives el almacenamiento USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Error en el funcionamiento del USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear almacenamiento USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Deseas formatear el almacenamiento USB y borrar todos los archivos almacenados aquí? ¡Esta acción no se puede cambiar!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clave compartida previamente"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificado"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1051,6 +1093,17 @@
<string name="storage_internal" msgid="7556050805474115618">"Almacenamiento interno"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Tarjeta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
<skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9db80ca..7c2cc2f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"El código PUK que has introducido no es correcto."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Los códigos PIN introducidos no coinciden."</string>
<string name="invalidPin" msgid="3850018445187475377">"Introduce un código PIN con una longitud comprendida entre cuatro y ocho dígitos."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Escribe un código PUK de ocho caracteres o más."</string>
<string name="needPuk" msgid="919668385956251611">"La tarjeta SIM está bloqueada con el código PUK. Introduce el código PUK para desbloquearla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduce el código PUK2 para desbloquear la tarjeta SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID de emisor de llamada entrante"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avión activado. Desactivar."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avión desactivado. Activar."</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"+100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+100"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios por los que tienes que pagar"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permite que la aplicación reciba y procese mensajes SMS. Las aplicaciones malintencionadas pueden controlar los mensajes o eliminarlos sin mostrarlos al usuario."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"recibir MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permite que la aplicación reciba y procese mensajes MMS. Las aplicaciones malintencionadas pueden controlar los mensajes o eliminarlos sin mostrarlos al usuario."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"recibir mensajes de emergencia"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permite que una aplicación reciba y procese mensajes de emergencia. Este permiso solo está disponible para las aplicaciones del sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar mensajes SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permite que la aplicación envíe mensajes SMS. Es posible que tengas que pagar si las aplicaciones malintencionadas envían mensajes sin tu confirmación."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"leer SMS o MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permite que una aplicación fuerce a cualquier actividad en segundo plano a cerrarse y volver a la pantalla anterior. No debería ser necesario nunca para las aplicaciones normales."</string>
<string name="permlab_dump" msgid="1681799862438954752">"recuperar estado interno del sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permite que la aplicación recupere el estado interno del sistema. Las aplicaciones malintencionadas pueden recuperar una amplia variedad de información protegida y privada que normalmente no deberían necesitar."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar contenido de la pantalla"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permite que una aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto de las mismas excepto las contraseñas."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Pone el administrador de actividades en estado de cierre. No realiza un cierre completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite enviar intentos a un administrador de dispositivos. Este permiso nunca debería ser necesario para las aplicaciones normales."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar orientación de la pantalla"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permite que una aplicación cambie la rotación de la pantalla en cualquier momento. No debería ser necesario nunca para las aplicaciones normales."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permite que una aplicación modifique la velocidad del puntero del trackpad o del ratón en cualquier momento. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"enviar señales Linux a aplicaciones"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"hacer que la aplicación se ejecute siempre"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"escribir datos de contacto"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos de contacto."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite que una aplicación modifique los datos de contacto (direcciones) almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar tus datos de contacto."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"leer eventos de calendario"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que una aplicación lea todos los eventos de calendario almacenados en el tablet. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite que una aplicación lea todos los eventos de calendario almacenados en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para enviar tus eventos de calendario a otras personas."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicación de campo cercano (NFC)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"interceptar y modificar todo el tráfico de red"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permite que una aplicación intercepte e inspeccione todo el tráfico de red para, por ejemplo, establecer una conexión VPN. Las aplicaciones malintencionadas pueden controlar, redirigir o modificar paquetes de red sin tu consentimiento."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permite que una aplicación intercepte e inspeccione todo el tráfico de red para establecer una conexión VPN. Las aplicaciones malintencionadas pueden controlar, redirigir o modificar paquetes de red sin el conocimiento del usuario."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"inhabilitar bloqueo del teclado"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que una aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Un ejemplo legítimo de este permiso es la inhabilitación por parte del teléfono del bloqueo del teclado cuando recibe una llamada telefónica entrante y su posterior habilitación cuando finaliza la llamada."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que una aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"realizar/recibir llamadas por Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que una aplicación utilice el servicio SIP para realizar o recibir llamadas de Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Control de la longitud y de los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar la frecuencia con la que se debe cambiar el bloqueo de pantalla"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptación de almacenamiento"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exige que se encripten los datos de la aplicación almacenados."</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Casa"</item>
<item msgid="869923650527136615">"Móvil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduce el código PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Introducir código PUK y nuevo código PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nuevo código PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Toca para contraseña"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introducir contraseña para desbloquear"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introducir PIN para desbloquear"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"No se ha insertado ninguna tarjeta SIM en el teléfono."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserta una tarjeta SIM"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Solo llamadas de emergencia"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Bloqueada para la red"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La tarjeta SIM está bloqueada con el código PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activas el almacenamiento USB, se detendrán algunas aplicaciones que estás utilizando y estas no estarán disponibles hasta que lo desactives."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"No se ha podido realizar la operación USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Aceptar"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatear USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatear tarjeta SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"¿Quieres formatear el USB y borrar todos los archivos? Esta acción no se puede deshacer."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de nivel 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Red privada virtual L2TP/IPSec basada en clave compartida previamente"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Red privada virtual L2TP/IPSec basada en certificado"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Almacenamiento interno"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Tarjeta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Almacenamiento USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificado de seguridad"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Este certificado es válido."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emitido para:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nombre común:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organización:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Departamento:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Emitido por:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validez:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Fecha de emisión:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Fecha de caducidad:"</string>
</resources>
diff --git a/core/res/res/values-fa-rIR/arrays.xml b/core/res/res/values-fa-rIR/arrays.xml
new file mode 100644
index 0000000..de0f368
--- /dev/null
+++ b/core/res/res/values-fa-rIR/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>32427908</item>
+ <item>53688046</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3fcb21d..48ad6f1 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK که نوشته اید صحیح نیست."</string>
<string name="mismatchPin" msgid="3695902225843339274">"پین هایی که وارد کرده اید با یکدیگر مطابقت ندارند."</string>
<string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که 4 تا 8 رقم باشد."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string>
<string name="needPuk" msgid="919668385956251611">"سیم کارت شما با PUK قفل شده است. کد PUK را برای بازگشایی آن بنویسید."</string>
<string name="needPuk2" msgid="4526033371987193070">"PUK2 را برای بازگشایی قفل سیم کارت بنویسید."</string>
<string name="ClipMmi" msgid="6952821216480289285">"شناسه تماس گیرنده ورودی"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"حالت هواپیما"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"حالت هواپیما روشن است"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"حالت هواپیما خاموش است"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"سیستم Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"سرویس های غیر رایگان"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"به برنامه کاربردی امکان می دهد که پیامک ها را دریافت کرده و آنها را پردازش کند. برنامه های مضر ممکن است پیام های شما را کنترل کرده یا بدون نمایش به شما، آنها را حذف کنند."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"دریافت MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"به برنامه کاربردی اجازه می دهد که پیام های MMS را دریافت کرده و آنها را پردازش کند. برنامه های مضر ممکن است پیام های شما را کنترل کرده یا بدون نمایش به شما، آنها را حذف کنند."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"دریافت پخش های اضطراری"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"به برنامه کاربردی امکان می دهد تا پیام های پخش اضطراری را دریافت کرده و پردازش کند. این مجوز فقط برای برنامه های سیستمی قابل استفاده است."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"ارسال پیامک ها"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"به برنامه کاربردی اجازه می دهد پیامک ارسال کند. برنامه های مضر ممکن است با ارسال پیام هایی بدون تأیید شما، هزینه هایی را برای شما ایجاد کنند."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"خواندن پیامک یا MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"به یک برنامه کاربردی اجازه می دهد تمام فعالیت های موجود در پیش زمینه را بسته و به عقب بازگردد. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
<string name="permlab_dump" msgid="1681799862438954752">"بازیابی وضعیت داخلی سیستم"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"به برنامه کاربردی اجازه می دهد وضعیت داخلی سیستم را بازیابی کند. برنامه های مضر می توانند حجم زیادی از اطلاعات شخصی و ایمن را بازیابی کنند که به طور معمول به آنها نیازی نخواهید داشت."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"بازیابی محتوای صفحه"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"به برنامه کاربردی اجازه می دهد تا محتوای پنجره فعال را بازیابی کند. برنامه های مضر می توانند کل محتوای پنجره را بازیابی کرده و تمام متون آن را بجز رمزهای ورود آزمایش کنند."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"خاموش شدن جزئی"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"مدیر فعالیت را در حالت خاموشی قرار می دهد. خاموشی را به صورت کامل انجام نمی دهد."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"به نگهدارنده اجازه می دهد مفاد را به یک سرپرست دستگاه ارسال کند. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"تغییر جهت صفحه"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"به یک برنامه کاربردی اجازه می دهد چرخش صفحه را در هر زمانی تغییر دهد. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشاره گر"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"به یک برنامه کاربردی این امکان را می دهد تا سرعت اشاره گر ماوس یا پد لمسی را در هر زمان تغییر دهد. برای برنامه های معمولی به این حالت نیاز نخواهید داشت."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"ارسال سیگنال های Linux برای برنامه ها"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"به برنامه کاربردی اجازه می دهد درخواست کند که سیگنال ارائه شده را به تمام فرایندهای ثابت ارسال کند."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"برنامه همیشه اجرا شود"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"نوشتن اطلاعات تماس"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در رایانه لوحی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"خواندن رویدادهای تقویم"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند. برنامه های مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در گوشی شما را بخواند. برنامه های کاربردی مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"به یک برنامه کاربردی برای ارتباط با برچسب های ارتباط راه نزدیک (NFC)، کارت ها و خواننده ها اجازه می دهد."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"رهگیری و تغییر تمام ترافیک شبکه"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"به برنامه کاربردی امکان می دهد تمام ترافیک شبکه را رهگیری کرده و آن را بررسی کند، به عنوان مثال برای برقراری اتصال VPN. برنامه های مضر ممکن است بدون اطلاع شما بسته های شبکه را کنترل کرده، مسیر آنها را تغییر دهند و یا تغییراتی در آن ایجاد کنند."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"به یک برنامه کاربردی امکان می دهد برای برقراری اتصال VPN، تمام ترافیک شبکه را رهگیری و بررسی کند. برنامه های مضر ممکن است بدون اطلاع شما بسته های شبکه را مدیریت کرده، مسیر آنها را تغییر دهند و یا تغییراتی در آنها ایجاد کنند."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"غیرفعال کردن قفل کلید"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"به یک برنامه کاربردی اجازه می دهد قفل کلید و حفاظت رمز ورود همراه با کلیه کلیدها را غیرفعال کند. یک نمونه قانونی از این مورد، غیرفعال شدن قفل کلید در هنگام دریافت تماس تلفنی و سپس فعال کردن قفل کلید پس از پایان تماس است."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"خواندن تنظیمات همگام سازی"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"به یک برنامه کاربردی امکان می دهد سیستم فایل حافظه پنهان را بخواند و بنویسد."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماس های اینترنتی"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"به یک برنامه کاربردی اجازخ می دهد از سرویس SIP جهت برقراری یا دریافت تماس های اینترنتی استفاده کند."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"کنترل طول و نویسه های مجاز رمزهای ورود قفل گشایی صفحه"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش های قفل گشایی صفحه"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"کنترل تعداد دفعات تغییر رمز ورود قفل صفحه"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"نیاز به رمزگذاری داده های برنامه کاربردی ذخیره شده دارد"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"خانه"</item>
<item msgid="869923650527136615">"تلفن همراه"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"محل کار"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"سایر موارد"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"کد پین را وارد کنید"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"PUK و کد پین جدید را وارد کنید"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"کد PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"کد پین جدید"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"لمس جهت ورود رمز ورود"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"رمز ورود را برای بازگشایی قفل وارد کنید"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"کد پین را برای بازگشایی قفل وارد کنید"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"سیم کارت درون تلفن نیست."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"لطفاً سیم کارت را وارد کنید."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"فقط تماس های اضطراری"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"شبکه قفل شد"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"سیم کارت با PUK قفل شده است."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"در صورت روشن کردن دستگاه ذخیره سازی USB، برخی از برنامه هایی که از آنها استفاده می کنید متوقف می شوند و تا زمانی که دستگاه ذخیره سازی USB را خاموش نکنید امکان استفاده از آنها وجود نخواهد داشت."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"عملکرد USB انجام نشد"</string>
<string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"فرمت کردن حافظه USB، همه فایل های ذخیره شده در آنجا پاک شود؟ عملکرد قابل بازگشت نیست!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"پروتکل تونلینگ لایه 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN بر پایه کلید از پیش مشترک شده"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN وابسته به گواهی"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
<string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"حافظه داخلی"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"کارت SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"حافظه USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"ویرایش..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"گواهی امنیتی"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"این گواهی معتبر است."</string>
+ <string name="issued_to" msgid="9032338008819841339">"صدور برای:"</string>
+ <string name="common_name" msgid="5745530093500062357">"نام عادی:"</string>
+ <string name="org_name" msgid="8868889052889991293">"سازمان:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"واحد سازمانی:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"صدور توسط:"</string>
+ <string name="validity_period" msgid="57988851973181309">"اعتبار:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"صدور در:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"تاریخ انقضا:"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 70e5ff7..5ddbb45 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Antamasi PUK-koodi on virheellinen."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Antamasi PIN-koodit eivät täsmää."</string>
<string name="invalidPin" msgid="3850018445187475377">"Anna 4–8-numeroinen PIN-koodi."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Kirjoita vähintään 8 numeron pituinen PUK-koodi."</string>
<string name="needPuk" msgid="919668385956251611">"SIM-korttisi on PUK-lukittu. Poista lukitus antamalla PUK-koodi."</string>
<string name="needPuk2" msgid="4526033371987193070">"Pura SIM-kortin esto antamalla PUK2-koodi."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Soittajan tunnus"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lentokonetila"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lentokonetila on KÄYTÖSSÄ"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lentokonetila on POIS KÄYTÖSTÄ"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Antaa sovelluksen vastaanottaa ja käsitellä tekstiviestejä. Haitalliset sovellukset saattavat valvoa viestejäsi tai poistaa niitä näyttämättä niitä sinulle."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"vastaanota multimediaviestejä"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Haitalliset sovellukset saattavat valvoa viestejäsi tai poistaa niitä näyttämättä niitä sinulle."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"vastaanota hätätilalähetyksiä"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Antaa sovelluksen vastaanottaa ja käsitellä hätätilalähetysten viestejä. Tämä lupa on vain järjestelmäsovelluksien käytettävissä."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"lähetä tekstiviestejä"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Antaa sovelluksen lähettää tekstiviestejä. Haitalliset sovellukset saattavat lähettää viestejä ilman lupaasi ja näin kasvattaa puhelinlaskuasi."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"lue multimedia- tai tekstiviestejä"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Antaa sovelluksen pakottaa etualalla olevan toiminnon sulkeutumaan ja siirtymään taustalle. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_dump" msgid="1681799862438954752">"nouda järjestelmän sisäinen tila"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Antaa sovelluksen saada selville järjestelmän sisäisen tilan. Haitalliset sovellukset voivat saada selville useita yksityisiä ja suojattuja tietoja, joita ne eivät tarvitse."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nouda näytön sisältö"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Antaa sovelluksen noutaa aktiivisen ikkunan sisällön. Haitalliset sovellukset voivat noutaa koko ikkunan sisällön ja tutkia sen koko tekstiä salasanoja lukuunottamatta."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"sulje puhelin osittain"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Asettaa toimintojen hallinnan sulkeutumistilaan. Ei sulje puhelinta kokonaan."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Antaa sovelluksen lähettää kyselyitä laitteen järjestelmänvalvojalle. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"muuta näytön suuntaa"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Antaa sovelluksen vaihtaa näytön suuntaa milloin tahansa. Ei tavallisten sovelluksien käyttöön."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"muuta osoittimen nopeutta"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Antaa sovelluksen muuttaa hiiren tai ohjauslevyn osoittimen nopeutta milloin tahansa. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"lähettää sovelluksiin Linux-signaaleja"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Antaa sovelluksen pyytää, että signaali lähetetään kaikille kiinteille prosesseille."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"aseta sovellus olemaan jatkuvasti käynnissä"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"kirjoita yhteystietoja"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Antaa sovelluksen muokata tablet-laitteellesi tallennettuja yhteystietoja (osoitteita). Haittasovellukset voivat käyttää tätä yhteystietojesi pyyhkimiseen tai muokkaamiseen."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Antaa sovelluksen muokata puhelimeen tallennettuja yhteystietoja (osoitteita). Haitalliset sovellukset voivat käyttää tätä yhteystietojen pyyhkimiseen tai muokkaamiseen."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"lue kalenteritapahtumia"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Antaa sovelluksen tarkastella kaikkia tablet-laitteellesi tallennettuja kalenteritapahtumia. Haittasovellukset voivat käyttää tätä tietojesi lähettämiseen muille ihmisille."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Antaa sovelluksen lukea kaikki puhelimeesi tallennetut kalenteritapahtumat. Haittasovellukset voivat käyttää tätä ominaisuutta kalenteritapahtumiesi lähettämiseen muille."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"hallitse Near Field Communication -tunnistusta"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Antaa sovelluksen viestiä Near Field Communication (NFC) -tunnisteiden, -korttien ja -lukijoiden kanssa."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"kaappaa ja muokkaa kaikkea verkkoliikennettä"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Antaa sovelluksen kaapata ja tarkastaa kaiken verkkoliikenteen, esimerkiksi VPN-yhteyden muodostamiseksi. Haitalliset sovellukset voivat tarkkailla, uudelleenohjata tai muokata verkkopaketteja tietämättäsi."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Antaa sovelluksen kaapata ja tarkastaa kaiken verkkoliikenteen VPN-yhteyden muodostamiseksi. Haitalliset sovellukset voivat tarkkailla, uudelleenohjata tai muokata verkkopaketteja tietämättäsi."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"poista näppäinlukitus käytöstä"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Antaa sovelluksen poistaa näppäinlukituksen ja siihen liittyvän salasanasuojauksen käytöstä. Esimerkki: puhelin poistaa näppäinlukituksen käytöstä saapuvan puhelun yhteydessä ja ottaa näppäinlukituksen takaisin käyttöön puhelun päätyttyä."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lue synkronointiasetuksia"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa sinne."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"soita/vastaanota internetpuheluita"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Antaa sovelluksen käyttää SIP-palvelua internetpuheluiden soittamiseen/vastaanottamiseen."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Määritä, miten usein ruudunlukituksen salasana tulee vaihtaa"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Aseta tallennustilan salaus"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pakota tallennettujen sovellustietojen salaus"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Puhelinnumero (koti)"</item>
<item msgid="869923650527136615">"Mobiili"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Työ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Muu"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Anna PIN-koodi"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Anna PUK-koodi ja uusi PIN-koodi"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-koodi"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Uusi PIN-koodi"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Kosketa ja anna salasana"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Poista lukitus antamalla salasana"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Poista lukitus antamalla PIN-koodi"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablet-laitteessa ei ole SIM-korttia."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Puhelimessa ei ole SIM-korttia."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Aseta SIM-kortti."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Vain hätäpuhelut"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Verkko lukittu"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortti on PUK-lukittu."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jos otat USB-tallennustilan käyttöön, osa käyttämistäsi sovelluksista pysähtyy eivätkä ne välttämättä ole käytössä kunnes poistat USB-tallennustilan käytöstä."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-toiminto epäonnistui"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Alusta USB-tila"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Alusta SD-kortti"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Haluatko alustaa USB-tilan ja poistaa kaikki siellä olevat tiedostot? Toimintoa ei voi peruuttaa!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Esijaettuun avaimeen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Varmenteeseen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
<string name="reset" msgid="2448168080964209908">"Palauta"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Sisäinen tallennustila"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kortti"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-tallennustila"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Muokkaa..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Suojausvarmenne"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Varmenne on voimassa."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Varmenteen saaja:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Yleinen nimi:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisaatio:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisaatioyksikkö:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Myöntäjä:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Voimassa:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Myönnetty:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Vanhenee:"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c618edf..fe1dd13 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"La clé PUK saisie est incorrecte."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Les codes PIN saisis ne correspondent pas."</string>
<string name="invalidPin" msgid="3850018445187475377">"Le code PIN doit compter de 4 à 8 chiffres."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Saisissez un code PUK comportant au moins huit chiffres."</string>
<string name="needPuk" msgid="919668385956251611">"Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller."</string>
<string name="needPuk2" msgid="4526033371987193070">"Saisissez la clé PUK2 pour débloquer la carte SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Numéro de l\'appelant (entrant)"</string>
@@ -138,7 +139,7 @@
<string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Votre tablette va s\'éteindre."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
- <string name="shutdown_confirm_question" msgid="6656441286856415014">"Voulez-vous éteindre votre mobile ?"</string>
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"Éteindre votre appareil ?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Récentes"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"Aucune application récente"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Options de la tablette"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permet à une application de recevoir et traiter des messages SMS. Des applications malveillantes peuvent surveiller ou effacer vos messages sans que vous les ayez lus."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"Réception des MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permet à une application de recevoir et traiter des messages MMS. Des applications malveillantes peuvent utiliser cette fonctionnalité pour surveiller ou effacer vos messages sans que vous les ayez lus."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"recevoir les messages de diffusion d\'urgence"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permet à l\'application de recevoir et de traiter les messages de diffusion d\'urgence. Cette autorisation est uniquement disponible pour les applications système."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"Envoi de messages SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permet aux applications d\'envoyer des messages SMS. Des applications malveillantes peuvent entraîner des frais en envoyant des messages sans vous en demander la confirmation."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"Lecture des SMS ou MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permet à une application de forcer une autre application exécutée au premier plan à se fermer et à passer en arrière-plan. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_dump" msgid="1681799862438954752">"Vérification de l\'état interne du système"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permet à l\'application de récupérer l\'état interne du système. Des applications malveillantes peuvent obtenir de nombreuses informations personnelles et sécurisées auxquelles elles ne devraient pas avoir accès."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"récupérer le contenu de l\'écran"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permet à l\'application de récupérer le contenu de la fenêtre active. Les applications malveillantes peuvent récupérer la totalité du contenu de la fenêtre et examiner l\'ensemble du texte, à l\'exception des mots de passe."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permet à l\'application d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standard ne devraient jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"Changement d\'orientation de l\'écran"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permet à une application de modifier la rotation de l\'écran à tout moment. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"changer la vitesse du pointeur"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permet à une application de modifier la vitesse du pointeur de la souris ou du pavé tactile à tout moment. Cette autorisation ne devrait jamais être nécessaire pour les applications standards."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Envoi de signaux Linux aux applications"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permet à une application de demander que le signal fourni soit envoyé à tous les processus persistants."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"Exécution de l\'application en continu"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"Édition des données d\'un contact"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet à une application de modifier les données (adresses) associées à vos contacts et stockées sur votre tablette. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier les données de vos contacts."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet à une application de modifier toutes les données de contact (adresses) enregistrées sur le téléphone. Des applications malveillantes peuvent utiliser cette fonctionnalité pour effacer ou modifier vos données de contact."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"lire des événements de l\'agenda"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre tablette. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet à une application de lire tous les événements de l\'agenda enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonctionnalité pour envoyer les événements de votre agenda à d\'autres personnes."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"contrôler la communication en champ proche"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permet à une application de communiquer avec des tags, cartes et lecteurs prenant en charge la communication en champ proche (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"intercepter et modifier l\'ensemble du trafic réseau"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permet à une application d\'intercepter et de contrôler l\'ensemble du trafic réseau, par exemple pour établir une connexion VPN. Des applications malveillantes sont susceptibles de surveiller, rediriger ou modifier les paquets réseau à votre insu."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permet à une application d\'intercepter et d\'inspecter l\'ensemble du trafic réseau pour établir une connexion VPN. Des applications malveillantes sont susceptibles de surveiller, rediriger ou modifier les paquets réseau à votre insu."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"Désactivation du verrouillage des touches"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet à une application de désactiver le verrouillage des touches et toute sécurité par mot de passe. Exemple : Votre téléphone désactive le verrouillage du clavier lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"Lecture des paramètres de synchronisation"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet à une application de lire et d\'écrire dans le système de fichiers en cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"effectuer/recevoir des appels Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permet à une application d\'utiliser le service SIP pour effectuer/recevoir des appels Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Gérer le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Contrôler la fréquence de modification du mot de passe de verrouillage de l\'écran"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir chiffrement du stockage"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exiger que les données d\'application stockées soient chiffrées"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Domicile"</item>
<item msgid="869923650527136615">"Mobile"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Professionnelle"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Autre"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Saisissez le code PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Saisissez le code PUK et le nouveau code PIN."</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Code PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nouveau code PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Saisie mot passe"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Saisissez le mot de passe pour procéder au déverrouillage."</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Saisissez le code PIN pour procéder au déverrouillage."</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Insérez une carte SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Appels d\'urgence uniquement"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Réseau verrouillé"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La carte SIM est verrouillée par clé PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si vous activez la mémoire de stockage USB, certaines applications en cours d\'utilisation seront fermées. Elles risquent de rester indisponibles jusqu\'à ce que la mémoire de stockage USB soit désactivée."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Échec du fonctionnement USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formater la mémoire USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formater la carte SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formater la mémoire de stockage USB en effaçant tous les fichiers ? Cette action est irréversible."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocole de tunnelisation de niveau 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basé sur une clé pré-partagée"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basé sur un certificat"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
<string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Mémoire de stockage interne"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Carte SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Mémoire de stockage USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Modifier..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de sécurité"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ce certificat est valide."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Émis à :"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nom commun :"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisation :"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unité d\'organisation :"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Émis par :"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validité :"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Émis le :"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Expire le :"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b87e99e..391fd08 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK koji ste unijeli nije točan."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN-ovi koje ste unijeli međusobno se ne podudaraju."</string>
<string name="invalidPin" msgid="3850018445187475377">"Unesite PIN koji ima od 4 do 8 brojeva."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Upišite PUK koji se sastoji od barem 8 brojeva."</string>
<string name="needPuk" msgid="919668385956251611">"Vaša je SIM kartica zaključana PUK-om. Unesite PUK kôd da biste je otključali."</string>
<string name="needPuk2" msgid="4526033371987193070">"Unesite PUK2 da biste odblokirali SIM karticu."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID dolaznog pozivatelja"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u zrakoplovu"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u zrakoplovu"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Isključen je način rada u zrakoplovu"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usluge koje se plaćaju"</string>
@@ -222,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Aplikaciji omogućuje prisilno zatvaranje ili otvaranje pozadinskih radnji. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
<string name="permlab_dump" msgid="1681799862438954752">"dohvaćanje internog stanja sustava"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Aplikaciji omogućuje dohvaćanje internog stanja sustava. Zlonamjerne aplikacije mogu dohvatiti širok raspon privatnih i sigurnih podataka koje uobičajeno uopće ne trebaju."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"dohvaćanje sadržaja zaslona"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Omogućuje aplikaciji dohvaćanje sadržaja aktivnog prozora. Zlonamjerne aplikacije mogu dohvatiti cijeli sadržaj prozora i pregledati sav njegov tekst osim zaporki."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"djelomično isključivanje"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Postavlja upravitelja za aktivnost u stanje mirovanja. Ne isključuje ga u potpunosti."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"sprečavanje promjene aplikacije"</string>
@@ -267,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Nositelju omogućuje slanje namjera administratoru uređaja. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"promjena orijentacije zaslona"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Aplikaciji omogućuje promjenu rotacije zaslona u svakom trenutku. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"promjena brzine pokazivača"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Omogućuje aplikaciji promjenu brzine pokazivača miša ili dodirne pločice u bilo koje vrijeme. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"slanje Linux signala u aplikaciju"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Aplikacijama omogućuje traženje zahtjeva da se dobiveni signal pošalje na sve trajne postupke."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"uvijek pokrenuta aplikacija"</string>
@@ -318,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"pisanje kontaktnih podataka"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem tabletnom uređaju. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu kontaktnih podataka."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu vaših kontaktnih podataka."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"čitanje kalendarskih događaja"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Aplikaciji omogućuje čitanje svih događaja na kalendaru koji su pohranjeni na tabletnom uređaju. Zlonamjerne aplikacije to mogu upotrijebiti za slanje događaja na kalendaru drugim ljudima."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Aplikaciji omogućuje čitanje svih kalendarskih događaja pohranjenih na računalu. Zlonamjerne aplikacije to mogu koristiti za slanje kalendarskih događaja drugim ljudima."</string>
@@ -455,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"upravljaj beskontaktnom (NFC) komunikacijom"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Aplikaciji omogućuje komunikaciju s Near Field Communication (NFC) oznakama, karticama i čitačima."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"presresti i izmijeniti sav promet u mreži"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Omogućuje aplikaciji presretanje i pregled svog mrežnog prometa kako bi, na primjer, uspostavila VPN vezu. Zlonamjerne aplikacije mogu pratiti, preusmjeravati ili mijenjati mrežne pakete bez vašeg znanja."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Omogućuje aplikaciji presretanje i pregled svog mrežnog prometa kako bi uspostavila VPN vezu. Zlonamjerne aplikacije mogu pratiti, preusmjeravati ili mijenjati mrežne pakete bez vašeg znanja."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"onemogući zaključavanje tipkovnice"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Aplikaciji omogućuje isključivanje zaključavanja tipkovnice i svih povezanih sigurnosnih zaporki. Jasan primjer toga daje isključivanje zaključavanja telefona kod primanja poziva, koje se ponovno aktivira nakon završetka poziva."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čitanje postavki sinkronizacije"</string>
@@ -482,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Aplikaciji omogućuje čitanje i pisanje u sustav datoteka predmemorije."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"zovi/primaj internetske pozive"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Aplikaciji omogućuje upotrebu SIP usluge za nazivanje/primanje internetskih poziva."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadziri duljinu i znakove dopuštene u zaporci za otključavanje zaslona"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -500,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Nadzirite koliko se često mora mijenjati zaporka za zaključavanje zaslona"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Postavi enkripciju za pohranu"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Zahtijevaj da pohranjeni podaci aplikacije budu kriptirani"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Početna"</item>
<item msgid="869923650527136615">"Mobilni"</item>
@@ -614,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Posao"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Unesite PIN kôd"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Unesite PUK i novi PIN kôd"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kôd"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Novi PIN kôd"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Dodir. za unos zaporke"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Unesite zaporku za otključavanje"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Unesite PIN za otključavanje"</string>
@@ -638,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"U telefonu nema SIM kartice."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Umetnite SIM karticu."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Samo hitni pozivi"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mreža je zaključana"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kartica je zaključana PUK-om."</string>
@@ -926,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ako uključite USB pohranjivanje, neke aplikacije koje koristite zaustavit će se i možda neće biti dostupne sve dok ne isključite USB pohranjivanje."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Rad USB-a nije uspio"</string>
<string name="dlg_ok" msgid="7376953167039865701">"U redu"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB memoriju"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj SD karticu"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatirati USB memoriju uz brisanje svih pohranjenih datoteka? Radnja se ne može poništiti!"</string>
@@ -993,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Tunelni protokol sloja 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unaprijed dijeljeni L2TP/IPSec VPN temeljen na ključu"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN temeljen na certifikatu"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
<string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1053,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Unutarnja pohrana"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD kartica"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB pohrana"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Uređivanje..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certifikat o sigurnosti"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ovaj je certifikat valjan."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Izdano do:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Zajednički naziv:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Tvrtka ili ustanova:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizacijska jedinica:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Izdao:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Vrijedi do:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Izdano dana:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Ističe dana:"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 0c2aef3..c5e16cf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"A megadott PUK-kód helytelen."</string>
<string name="mismatchPin" msgid="3695902225843339274">"A beírt PIN-kódok nem egyeznek."</string>
<string name="invalidPin" msgid="3850018445187475377">"Írjon be egy 4-8 számjegyű PIN-kódot."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"8 számjegyű vagy hosszabb PUK kódot írjon be."</string>
<string name="needPuk" msgid="919668385956251611">"A SIM-kártya le van zárva a PUK-kóddal. A feloldáshoz adja meg a PUK-kódot."</string>
<string name="needPuk2" msgid="4526033371987193070">"A SIM-kártya feloldásához adja meg a PUK2-kódot."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Beérkező hívóazonosító"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Repülőgép üzemmód"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Repülőgép üzemmód bekapcsolva"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Repülőgép üzemmód kikapcsolva"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Fizetős szolgáltatások"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Lehetővé teszi az alkalmazás számára az SMS-ek fogadását és feldolgozását. A rosszindulatú alkalmazások megfigyelhetik vagy törölhetik az üzeneteket anélkül, hogy Ön látná."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMS fogadása"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Lehetővé teszi az alkalmazás számára, hogy fogadjon és feldolgozzon MMS-eket. A rosszindulatú alkalmazások megfigyelhetik vagy törölhetik az üzeneteket anélkül, hogy Ön látná."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"vészhelyzeti közlemények fogadása"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Lehetővé teszi, hogy az alkalmazás fogadja és feldolgozza a vészhelyzeti közleményeket. Ez az engedély csak a rendszeralkalmazások számára érhető el."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"SMS-ek küldése"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Lehetővé teszi az alkalmazás számára SMS küldését. A rosszindulatú alkalmazások az Ön engedélye nélkül küldhetnek üzenetet, ami megnövelheti a kiadásait."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMS vagy MMS olvasása"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Lehetővé teszi egy alkalmazás számára, hogy bármilyen tevékenységet bezárjon és a háttérbe kényszerítsen. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_dump" msgid="1681799862438954752">"rendszer belső állapotának lekérése"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Lehetővé teszi az alkalmazás számára, hogy lekérje a rendszer belső állapotát. A rosszindulatú programok lekérhetnek számos olyan privát és biztonságos adatot, amelyekre normál esetben soha nincs szükségük."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"a képernyő tartalmának lekérése"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Lehetővé teszi, hogy az alkalmazás lekérje az aktív ablak tartalmát. A rosszindulatú alkalmazások lekérhetik a teljes ablak tartalmát, és megvizsgálhatják annak összes szövegét, kivéve a jelszavakat."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"részleges rendszerleállítás"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Leállítás állapotba helyezi a tevékenységkezelőt. Nem hajtja végre a teljes leállítást."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Lehetővé teszi a használó számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"képernyő irányának módosítása"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Lehetővé teszi egy alkalmazás számára a képernyő elforgatásának módosítását. A normál alkalmazásoknak erre soha nincs szüksége."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"mutató sebességének módosítása"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Lehetővé teszi, hogy az alkalmazás bármikor megváltoztassa az egér vagy az érintőpad mutatójának sebességét. Normál alkalmazásoknak soha nem lehet rá szükségük."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux jelek küldése alkalmazásoknak"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Lehetővé teszi az alkalmazás számára, hogy a megadott jelet elküldje az összes állandó folyamatnak."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"alkalmazások folyamatos futtatása"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"névjegyadatok írása"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lehetővé teszi az alkalmazások számára, hogy módosítsák a táblagépen tárolt névjegyadatokat (címeket). A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy töröljék vagy módosítsák a névjegyadatokat."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt névjegy- (cím-) adatokat. A rosszindulatú alkalmazások felhasználhatják ezt a névjegyadatok törlésére vagy módosítására."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"naptári események olvasása"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lehetővé teszi az alkalmazások számára, hogy elolvassák a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy elküldjék az eseményeket másoknak."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Lehetővé teszi az alkalmazás számára, hogy elolvassa a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt az események mások részére való elküldésére használhatják fel."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"NFC technológia vezérlése"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Lehetővé teszi az alkalmazások számára, hogy NFC (Near Field Communication - kis hatósugarú vezeték nélküli kommunikáció) technológiát használó címkékkel, kártyákkal és leolvasókkal kommunikáljanak."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"teljes hálózati forgalom elfogása és módosítása"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Lehetővé teszi egy alkalmazás számára, hogy elfogja és megvizsgálja a teljes hálózati forgalmat, például VPN-kapcsolat létrehozásához. A rosszindulatú alkalmazások a tudta nélkül figyelhetik, átirányíthatják vagy módosíthatják a hálózati csomagokat."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Lehetővé teszi egy alkalmazás számára, hogy elfogja és megvizsgálja a teljes hálózati forgalmat VPN-kapcsolat létrehozásához. A rosszindulatú alkalmazások a tudta nélkül figyelhetik, átirányíthatják vagy módosíthatják a hálózati csomagokat."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"billentyűzár kikapcsolása"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lehetővé teszi egy alkalmazás számára a billentyűzár és a kapcsolódó jelszavas biztonság kikapcsolását. Ennek egy szabályos példája, amikor a telefon kikapcsolja a billentyűzárat egy beérkező hívás fogadásakor, majd a hívás befejezése után újra bekapcsolja azt."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"szinkronizálási beállítások olvasása"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Lehetővé teszi egy alkalmazás számára a gyorsítótár fájlrendszerének olvasását és írását."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"internetes hívások kezdeményezése és fogadása"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Lehetővé teszi az alkalmazások számára a SIP-szolgáltatás használatát internetes hívások kezdeményezésére és fogadására."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Adja meg, hogy milyen gyakran kell módosítani a képernyőzár jelszavát"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tárhelytitkosítás beállítása"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Megköveteli a tárolt alkalmazásadatok titkosítását"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Otthoni"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Munkahely"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Egyéb"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Adja meg a PIN-kódot"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Írja be a PUK kódot, majd az új PIN kódot"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kód"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Új PIN kód"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Érintse meg jelszóhoz"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"A feloldáshoz írja be a jelszót"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Feloldáshoz írja be a PIN kódot"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nincs SIM-kártya a táblagépben."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nincs SIM-kártya a telefonban."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Kérjük, helyezzen be egy SIM-kártyát."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Csak segélyhívások"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"A hálózat lezárva"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"A SIM-kártya le van zárva a PUK-kóddal."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ha bekapcsolja az USB-tárat, egyes jelenleg használt alkalmazások leállnak és lehet, hogy nem lesznek elérhetők a tár újbóli kikapcsolásáig."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Az USB művelet sikertelen"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Az USB-tár formázása"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kártya formázása"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formázza az USB-tárat, törölve az összes ott tárolt fájlt? A művelet nem vonható vissza!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"L2TP protokoll"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Osztott kulcs (PSK) alapú L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Tanúsítvány alapú L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string>
<string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Belső tárhely"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kártya"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-tár"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Szerkesztés..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Biztonsági tanúsítvány"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"A tanúsítvány érvényes."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Kiállítva a következőnek:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Név:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Szervezet:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Szervezeti egység:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Kiállította:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Érvényesség:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Kiállítva:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Lejár:"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 00e2dd4..4e7504a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK yang Anda ketikkan salah."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN yang Anda masukkan tidak sesuai."</string>
<string name="invalidPin" msgid="3850018445187475377">"Ketikkan PIN berupa 4 sampai 8 angka."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Ketik PUK yang terdiri dari 8 angka atau lebih."</string>
<string name="needPuk" msgid="919668385956251611">"Kartu SIM Anda dikunci PUK. Ketikkan kode PUK untuk membukanya."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ketikkan PUK2 untuk membuka kartu SIM"</string>
<string name="ClipMmi" msgid="6952821216480289285">"Nomor Penelepon Masuk"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat HIDUP"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Layanan berbayar"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Mengizinkan aplikasi menerima dan memproses pesan SMS. Aplikasi hasad dapat memonitor pesan Anda atau menghapusnya tanpa menampilkannya kepada Anda."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"menerima MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Mengizinkan aplikasi menerima dan memproses pesan SMS. Aplikasi hasad dapat memonitor pesan atau menghapusnya tanpa menampilkannya kepada Anda."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"terima siaran darurat"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Memungkinkan aplikasi menerima dan memproses pesan siaran darurat. Izin ini hanya tersedia untuk aplikasi sistem."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"kirim pesan SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Mengizinkan aplikasi mengirim pesan SMS. Aplikasi hasad dapat membebankan biaya kepada Anda dengan mengirim pesan tanpa konfirmasi dari Anda."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"baca SMS atau MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Mengizinkan aplikasi menutup dan mengembalikan aktivitas apa pun yang berada di latar depan secara paksa. Tidak pernah diperlukan untuk aplikasi normal."</string>
<string name="permlab_dump" msgid="1681799862438954752">"ambil kondisi internal sistem"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Mengizinkan aplikasi mengambil kondisi internal sistem. Aplikasi hasad dapat menarik berbagai informasi pribadi dan aman yang biasanya tidak dibutuhkan."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ambil konten layar"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Memungkinkan aplikasi mengambil konten jendela aktif. Aplikasi berbahaya dapat mengambil seluruh konten jendela dan memeriksa semua teks yang ada di dalamnya kecuali sandi."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"penghentian sebagian"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Letakkan pengelola aktivitas dalam kondisi mati. Tidak melakukan penonaktifan penuh."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak diperlukan untuk aplikasi normal."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ubah orientasi layar"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Mengizinkan aplikasi mengubah rotasi layar kapan saja. Tidak diperlukan untuk aplikasi normal."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ubah kecepatan penunjuk"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Memungkinkan aplikasi mengubah kecepatan penunjuk mouse atau trackpad kapan saja. Tidak diperlukan untuk aplikasi normal."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"kirim sinyal Linux ke aplikasi"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Mengizinkan aplikasi meminta sinyal yang diberikan untuk dikirimkan ke semua proses yang ada."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"jadikan aplikasi selalu berjalan"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"tuliskan data kenalan"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Mengizinkan aplikasi memodifikasi data kenalan (alamat) yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk menghapus atau mengubah data kenalan."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Mengizinkan aplikasi mengubah data kenalan (alamat) yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data kenalan Anda."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"membaca acara kalender."</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Mengizinkan aplikasi membaca semua acara kalender yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk mengirim acara kalender ke orang lain."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Mengizinkan aplikasi membaca semua acara kalender yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk mengirimkan acara kalender ke orang lain."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontrol NFC"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Mengizinkan aplikasi berkomunikasi dengan tag, kartu, dan pembaca Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"cegat dan ubah semua lalu lintas jaringan"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Memungkinkan aplikasi mencegat dan memeriksa semua lalu lintas jaringan, misalnya untuk membuat sambungan VPN. Aplikasi berbahaya dapat memantau, mengalihkan, atau mengubah paket jaringan tanpa sepengetahuan Anda."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Memungkinkan aplikasi mencegat dan memeriksa semua lalu lintas jaringan untuk melakukan sambungan VPN. Aplikasi berbahaya dapat memantau, mengalihkan, atau mengubah paket jaringan tanpa sepengetahuan Anda."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"nonaktifkan kunci tombol"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Mengizinkan aplikasi menonaktifkan keylock dan keamanan sandi terkait mana pun. Contoh yang sah adalah ponsel menonaktifkan keylock ketika menerima panggilan telepon masuk, kemudian mengaktifkan keylock sekali lagi setelah panggilan selesai."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca setelan sinkron"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Mengizinkan aplikasi membaca dan menulis filesystem tembolok."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"lakukan//terima panggilan internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Mengizinkan aplikasi menggunakan layanan SIP melakukan/menerima telepon internet"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrol panjangnya dan karakter yang diizinkan dalam sandi pembuka layar"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrol seberapa sering sandi pengunci layar harus diganti"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setel enkripsi penyimpanan"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Mengharuskan data aplikasi yang disimpan untuk dienkripsi"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Rumah"</item>
<item msgid="869923650527136615">"Seluler"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerjaan"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Lainnya"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Masukkan kode PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Masukkan kode PUK dan kode PIN baru"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kode PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Kode Pin Baru"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Sentuh untuk memasukkan sandi"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Masukkan sandi untuk membuka"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Masukkan PIN untuk membuka kunci"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tidak ada Kartu SIM di dalam ponsel."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Masukkan kartu SIM"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan darurat saja"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Jaringan terkunci"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kartu SIM terkunci PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika Anda menghidupkan penyimpanan USB, sebagian aplikasi yang Anda gunakan akan berhenti dan mungkin tidak tersedia sampai Anda mematikan penyimpanan USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operasi USB gagal"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format penyimpanan USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kartu SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format penyimpanan USB, menghapus semua berkas yang disimpan di sana? Tindakan tidak dapat diurungkan!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol Penyaluran Lapis 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Kunci pra-bagi berbasis L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikat berbasis L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Pilih berkas"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada berkas yang dipilih"</string>
<string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Penyimpanan Internal"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Kartu SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Penyimpanan USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Edit..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Sertifikat keamanan"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikat ini valid."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Diterbitkan ke:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nama umum:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisasi:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unit organisasi:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Diterbitkan oleh:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validitas:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Diterbitkan pada:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Kedaluwarsa pada:"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 0d78861..10d1787 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Il PUK digitato è errato."</string>
<string name="mismatchPin" msgid="3695902225843339274">"I PIN inseriti non corrispondono."</string>
<string name="invalidPin" msgid="3850018445187475377">"Il PIN deve essere di 4-8 numeri."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Digita un PUK formato da almeno 8 numeri."</string>
<string name="needPuk" msgid="919668385956251611">"La SIM è bloccata tramite PUK. Digita il codice PUK per sbloccarla."</string>
<string name="needPuk2" msgid="4526033371987193070">"Digita il PUK2 per sbloccare la SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID chiamante in entrata"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servizi che prevedono un costo"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Consente il ricevimento e l\'elaborazione di SMS da parte dell\'applicazione. Le applicazioni dannose potrebbero monitorare i messaggi o eliminarli senza visualizzarli."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"ricezione MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Consente il ricevimento e l\'elaborazione di MMS da parte dell\'applicazione. Le applicazioni dannose potrebbero monitorare i messaggi o eliminarli senza visualizzarli."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"ricezione di trasmissioni di emergenza"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Consente all\'applicazione di ricevere ed elaborare messaggi di trasmissioni di emergenza. Tale autorizzazione è disponibile solo per applicazioni di sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"invio SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Consente all\'applicazione di inviare messaggi SMS. Le applicazioni dannose potrebbero inviare messaggi a tua insaputa facendoti sostenere dei costi."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"lettura SMS o MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Consente a un\'applicazione di forzare la chiusura di attività in primo piano. Non dovrebbe essere mai necessario per le normali applicazioni."</string>
<string name="permlab_dump" msgid="1681799862438954752">"recupero stato interno del sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Consente all\'applicazione di recuperare lo stato interno del sistema. Le applicazioni dannose potrebbero recuperare molte informazioni riservate e protette di cui non dovrebbero avere mai bisogno."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recupero dei contenuti della schermata"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Consente all\'applicazione di recuperare i contenuti della finestra attiva. Le applicazioni dannose potrebbero recuperare tutti i contenuti della finestra ed esaminare tutto il testo ad eccezione delle password."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"chiusura parziale"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Consente l\'invio di intent a un amministratore del dispositivo. L\'autorizzazione non deve mai essere necessaria per le normali applicazioni."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"modifica orientamento dello schermo"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Consente a un\'applicazione di cambiare la rotazione dello schermo in qualsiasi momento. Non dovrebbe essere mai necessario per le normali applicazioni."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambio velocità del puntatore"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Consente a un\'applicazione di modificare la velocità del puntatore del mouse o del trackpad in qualsiasi momento. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"invio segnali Linuz alle applicazioni"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Consente all\'applicazione di richiedere l\'invio del segnale fornito a tutti i processi persistenti."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"esecuzione permanente delle applicazioni"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"scrittura dati di contatto"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Consente a un\'applicazione di modificare i dati (gli indirizzi) di contatto memorizzati sul tablet. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati di contatto."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Consente a un\'applicazione di modificare i dati (gli indirizzi) di contatto memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati di contatto."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"leggere eventi di calendario"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Consente la lettura da parte di un\'applicazione di tutti gli eventi di calendario memorizzati sul tablet. Le applicazioni dannose possono sfruttare questa possibilità per inviare i tuoi eventi di calendario ad altre persone."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Consente la lettura da parte di un\'applicazione di tutti gli eventi di calendario memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per inviare i tuoi eventi di calendario ad altre persone."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controllo Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Consente a un\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"intercettazione e modifica di tutto il traffico di rete"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Consente a un\'applicazione di intercettare e controllare tutto il traffico di rete, ad esempio per stabilire una connessione VPN. Le applicazioni dannose potrebbero monitorare, reindirizzare o modificare i pacchetti di rete a tua insaputa."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Consente a un\'applicazione di intercettare e controllare tutto il traffico di rete per stabilire una connessione VPN. Le applicazioni dannose potrebbero monitorare, reindirizzare o modificare i pacchetti di rete a tua insaputa."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"disattivazione blocco tastiera"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Consente la disattivazione da parte di un\'applicazione del blocco tastiera e di eventuali protezioni tramite password associate. Un valido esempio è la disattivazione da parte del telefono del blocco tastiera quando riceve una telefonata in entrata, e la successiva riattivazione del blocco al termine della chiamata."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lettura impostazioni di sincronizz."</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Consente a un\'applicazione di leggere e scrivere il filesystem nella cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"effettuazione/ricezione chiamate Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Consente a un\'applicazione di utilizzare il servizio SIP per effettuare/ricevere chiamate Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabilisci la frequenza di modifica della password di blocco dello schermo"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Imposta crittografia archivio"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Richiede la crittografia dei dati applicazione memorizzati"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Casa"</item>
<item msgid="869923650527136615">"Cellulare"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Lavoro"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altro"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Inserisci il PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Inserisci il PUK e il nuovo codice PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codice PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nuovo codice PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Tocca e inserisci password"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Inserisci password per sbloccare"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Inserisci PIN per sbloccare"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nessuna scheda SIM presente nel tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nessuna SIM presente nel telefono."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inserisci una SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Solo chiamate di emergenza"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rete bloccata"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"La SIM è bloccata tramite PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se attivi l\'archivio USB, alcune applicazioni in uso si bloccheranno e potrebbero risultare non disponibili finché non disattiverai l\'archivio USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operazione USB non riuscita"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatta archivio USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatta scheda SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formattare l\'archivio USB cancellando tutti i file memorizzati al suo interno? Questa azione è irreversibile."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocollo di tunneling livello 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basata su chiave precondivisa"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basata su certificato"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Scegli file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string>
<string name="reset" msgid="2448168080964209908">"Reimposta"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Archivio interno"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Scheda SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Archivio USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Modifica..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificato di protezione"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Questo certificato è valido."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Rilasciato a:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nome comune:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizzazione:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unità organizzativa:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Rilasciato da:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validità:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Rilasciato il:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Scade il:"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6b50982..3fce696 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"ה-PUK שהקלדת שגוי."</string>
<string name="mismatchPin" msgid="3695902225843339274">"קודי ה-PIN שהזנת לא מתאימים."</string>
<string name="invalidPin" msgid="3850018445187475377">"הקלד PIN שאורכו 4 עד 8 ספרות."</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="ClipMmi" msgid="6952821216480289285">"זיהוי מתקשר של שיחה נכנסת"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"מצב טיסה"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"מצב טיסה מופעל"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"מצב טיסה כבוי"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
<string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"שירותים שעולים לך כסף"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"מאפשר ליישום לקבל ולעבד הודעות SMS. יישומים זדוניים עלולים לעקוב אחר ההודעות או למחוק אותן מבלי להציג אותם לך."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"קבל MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"מאפשר ליישום לקבל ולעבד הודעות MMS. יישומים זדוניים עלולים לעקוב אחר ההודעות או למחוק אותן מבלי להציג אותן לך."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"קבלת שידורי חירום"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"מאפשר ליישום לקבל ולעבד הודעות של שידורי חירום. הרשאה זו זמינה רק ליישומי מערכת."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"שלח הודעות SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"מאפשר ליישום לשלוח הודעות SMS. יישומים זדוניים עלולים לגרום לחיובים על ידי שליחת הודעות ללא אישורך."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"קריאת SMS או MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"מאפשר ליישום לאלץ פעילות כלשהי בחזית להיסגר ולעבור לרקע. לעולם לא אמור להיות דרוש ליישומים רגילים."</string>
<string name="permlab_dump" msgid="1681799862438954752">"אחזור מצב פנימי של המערכת"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"מאפשר ליישום לאחזר את המצב הפנימי של המערכת. יישומים זדוניים עלולים לאחזר מגוון רחב של מידע פרטי ומאובטח שלא אמור להיות להם צורך בו."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"אחזור תוכן המסך"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"מאפשר ליישום לאחזר את התוכן של החלון הפעיל. יישומים זדוניים עשויים לאחזר את כל תוכן החלון ולבחון את כל הטקסט שהוא מכיל פרט לסיסמאות."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"מאפשר למשתמש לשלוח כוונות למנהל התקן. לא אמור להידרש לעולם ביישומים רגילים."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"שנה את כיוון המסך"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"מאפשר ליישום לשנות את סיבוב המסך בכל עת. לא אמור להידרש לעולם ביישומים רגילים."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"שינוי מהירות המצביע"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"מאפשר ליישום לשנות את מהירות מצביע העכבר או משטח העקיבה בכל עת. הגדרה זו אף פעם לא נחוצה עבור יישומים רגילים."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"שלח אותות Linux ליישומים"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"מאפשר ליישום לבקש שהאות המסופק יישלח לכל התהליכים המתמשכים."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"הגדר את היישום לפעול תמיד"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"כתוב נתוני איש קשר"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"מאפשר ליישום לשנות את נתוני הקשר (כתובות) המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני אנשי הקשר."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"מאפשר ליישום לשנות את הנתונים של אנשי הקשר (כתובות) המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים של אנשי הקשר."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"קרא אירועי לוח שנה"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"מאפשר ליישום לקרוא את כל נתוני לוח השנה המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה לאנשים אחרים."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"מאפשר ליישום לקרוא את כל אירועי לוח השנה המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה שלך לאנשים אחרים."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"שלוט ב-Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"מאפשר ליישום לקיים תקשורת עם תגיות, כרטיסים וקוראים מסוג Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"לעכב ולשנות את כל תעבורת הרשת"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"מאפשר ליישום לעכב ולבדוק את כל תעבורת הרשת, לדוגמה, ליצור חיבור VPN. יישומים זדוניים עלולים לנטר, לנתב מחדש או לשנות מנות רשת ללא ידיעתך."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"מאפשר ליישום לעכב ולבדוק את כל תעבורת הרשת כדי ליצור חיבור VPN. יישומים זדוניים עלולים לנטר, לנתב מחדש או לשנות מנות רשת ללא ידיעתך."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"השבת נעילת מקשים"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"מאפשר ליישום להשבית את נעילת המקשים ואבטחת סיסמה משויכת. דוגמה תקפה לכך היא טלפון המשבית את נעילת המקשים בעת קבלת שיחת טלפון נכנסת, ולאחר מכן מפעיל מחדש את נעילת המקשים עם סיום השיחה."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"קרא הגדרות סנכרון"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"מאפשר ליישום לקרוא ולכתוב במערכת הקבצים של הקובץ השמור."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"בצע/קבל שיחות אינטרנט"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"מאפשר ליישום להשתמש בשירות SIP כדי לבצע/לקבל שיחות אינטרנט."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"שלוט באורך ובמספר התווים המותרים בסיסמאות לביטול נעילת מסך"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"שלוט בתדירות שבה הסיסמה של נעילת המסך חייבת להשתנות"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"הגדר הצפנת אחסון"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"דורש שנתוני היישום המאוחסנים יהיו מוצפנים"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"בית"</item>
<item msgid="869923650527136615">"נייד"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"עבודה"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"אחר"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"הזן קוד PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"הזן PUK וקוד PIN חדש"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"קוד PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"קוד PIN חדש"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"גע כדי להזין סיסמה"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"הזן סיסמה לביטול הנעילה"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"הזן PIN לביטול נעילה"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"אין כרטיס SIM בטבלט."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"אין כרטיס SIM בטלפון."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"הכנס כרטיס SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"אם תפעיל אחסון USB, חלק מהיישומים שבהם אתה משתמש יעצרו ולא יהיו זמינים עד שתכבה את אחסון ה-USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"הפעלת ה-USB נכשלה"</string>
<string name="dlg_ok" msgid="7376953167039865701">"אישור"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"לפרמט את אמצעי האחסון מסוג USB, תוך מחיקת כל הקבצים? הפעולה בלתי הפיכה!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN של L2TP/IPSec המבוסס על מפתח משותף מראש"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN המבוסס על אישור"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
<string name="reset" msgid="2448168080964209908">"אפס"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"אחסון פנימי"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"כרטיס SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"אמצעי אחסון מסוג USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"ערוך..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"אישור אבטחה"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"אישור זה תקף."</string>
+ <string name="issued_to" msgid="9032338008819841339">"הופק עבור:"</string>
+ <string name="common_name" msgid="5745530093500062357">"שם משותף:"</string>
+ <string name="org_name" msgid="8868889052889991293">"ארגון:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"יחידה ארגונית:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"הופק על ידי:"</string>
+ <string name="validity_period" msgid="57988851973181309">"חוקיות:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"הונפק בתאריך:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"פג תוקף ב:"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index bdad7b6..9771a29 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"入力したPUKは正しくありません。"</string>
<string name="mismatchPin" msgid="3695902225843339274">"入力したPINが一致しません。"</string>
<string name="invalidPin" msgid="3850018445187475377">"4~8桁の数字のPINを入力してください。"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"PUKは8桁以上で入力してください。"</string>
<string name="needPuk" msgid="919668385956251611">"SIMカードはPUKでロックされています。ロックを解除するにはPUKコードを入力してください。"</string>
<string name="needPuk2" msgid="4526033371987193070">"SIMカードのロック解除のためPUK2を入力します。"</string>
<string name="ClipMmi" msgid="6952821216480289285">"着信時の発信者番号"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"機内モード"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"機内モードON"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"機内モードOFF"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100超"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100超"</string>
<string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
<string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"料金の発生するサービス"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"SMSメッセージの受信と処理をアプリケーションに許可します。悪意のあるアプリケーションがメッセージを監視したり、表示せずに削除する恐れがあります。"</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMSの受信"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"MMSメッセージの受信と処理をアプリケーションに許可します。悪意のあるアプリケーションがメッセージを監視したり、表示せずに削除する恐れがあります。"</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"緊急放送の受信"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"緊急放送メッセージの取得と処理をアプリケーションに許可します。これはシステムアプリケーションのみ利用できる権限です。"</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"SMSメッセージの送信"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"SMSメッセージの送信をアプリケーションに許可します。悪意のあるアプリケーションが確認なしでメッセージを送信し、料金が発生する恐れがあります。"</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMSの読み取り"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"フォアグラウンドで実行されている操作を強制終了して戻ることをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string>
<string name="permlab_dump" msgid="1681799862438954752">"システムの内部状態の取得"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"システムの内部状態の取得をアプリケーションに許可します。悪意のあるアプリケーションが、通常は必要としない広範囲にわたる非公開の機密情報を取得する恐れがあります。"</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"画面のコンテンツの取得"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"作業中のウィンドウのコンテンツを取得することをアプリケーションに許可します。悪意のあるアプリケーションがウィンドウのコンテンツ全体を取得し、パスワード以外のテキストをすべて調べる可能性があります。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"デバイス管理者へのintentの送信を所有者に許可します。通常のアプリケーションでは不要です。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"画面の向きの変更"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"いつでも画面の回転を変更することをアプリケーションに許可します。通常のアプリケーションにはまったく必要ありません。"</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ポインタの速度の変更"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"マウスまたはトラックパッドのポインタの速度をいつでも変更することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linuxのシグナルをアプリケーションに送信"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"受信した電波を継続プロセスに送信することをアプリケーションに許可します。"</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"アプリケーションを常に実行する"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"連絡先データの書き込み"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"タブレットに保存されている連絡先(アドレス)データの変更をアプリケーションに許可します。この許可を悪意のあるアプリケーションに利用されると、連絡先データが消去または変更される恐れがあります。"</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"端末に保存した連絡先(アドレス)データの変更をアプリケーションに許可します。悪意のあるアプリケーションが連絡先データを消去/変更する恐れがあります。"</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"カレンダーの予定の読み取り"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"タブレットに保存されているカレンダーの予定の読み取りをアプリケーションに許可します。この許可を悪意のあるアプリケーションに利用されると、カレンダーの予定が他人に送信される恐れがあります。"</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"端末に保存したカレンダーの予定の読み取りをアプリケーションに許可します。悪意のあるアプリケーションがカレンダーの予定を他人に送信する恐れがあります。"</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"NFCの管理"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"NFCタグ、カード、リーダーとの通信をアプリケーションに許可します。"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"すべてのネットワークトラフィックの傍受と変更"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"VPN接続の確立も含めてすべてのネットワークトラフィックを傍受、検査することをアプリケーションに許可します。悪意のあるアプリケーションが通知せずにネットワークパケットを監視、リダイレクト、変更する恐れがあります。"</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"アプリケーションがVPN接続の確立のためにすべてのネットワークトラフィックを傍受、検査することを許可します。悪意のあるアプリケーションによって通知なしにネットワークパケットが監視、リダイレクト、変更される恐れがあります。"</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"キーロックを無効にする"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"キーロックや関連するパスワードセキュリティを無効にすることをアプリケーションに許可します。正当な利用の例では、かかってきた電話を受信する際にキーロックを無効にし、通話の終了時にキーロックを有効にし直します。"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"同期設定の読み取り"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"キャッシュファイルシステムへの読み書きをアプリケーションに許可します。"</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"インターネット通話の発着信"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"インターネット通話の発着信にSIPサービスを使用することをアプリケーションに許可します。"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"画面ロック解除パスワードの長さと使用できる文字数を制御する"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"ロック解除パスワードの変更が必要になる頻度を指定します"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"ストレージ暗号化の設定"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"保存したアプリケーションデータが暗号化されるようにする"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"自宅"</item>
<item msgid="869923650527136615">"携帯"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"勤務先"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"その他"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PINコードを入力"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"PUKと新しいPINコードを入力"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUKコード"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"新しいPINコード"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"タップしてパスワードを入力"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"パスワードを入力"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"PINを入力"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"タブレット内にSIMカードがありません。"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIMカードが挿入されていません"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"SIMカードを挿入してください。"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USBストレージをONにすると、使用中のアプリケーションの一部が停止し、USBストレージをOFFにするまで使用できなくなる場合があります。"</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB操作に失敗しました"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USBストレージをフォーマットして、保存されているすべてのファイルを消去しますか?この操作は元に戻せません。"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"レイヤー2トンネリングプロトコル"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPNベースの事前共有鍵"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPNベースの証明書"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
<string name="reset" msgid="2448168080964209908">"リセット"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"内部ストレージ"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SDカード"</string>
<string name="storage_usb" msgid="3017954059538517278">"USBストレージ"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"編集..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"セキュリティ証明書"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"この証明書は有効です。"</string>
+ <string name="issued_to" msgid="9032338008819841339">"発行先:"</string>
+ <string name="common_name" msgid="5745530093500062357">"共通名:"</string>
+ <string name="org_name" msgid="8868889052889991293">"組織:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"組織単位:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"発行者:"</string>
+ <string name="validity_period" msgid="57988851973181309">"有効期間:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"発行:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"有効期限:"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5a3584a..a50f743 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"입력한 PUK가 올바르지 않습니다."</string>
<string name="mismatchPin" msgid="3695902225843339274">"입력한 PIN이 일치하지 않습니다."</string>
<string name="invalidPin" msgid="3850018445187475377">"4~ 8자리 숫자로 된 PIN을 입력하세요."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"8자리 이상의 숫자 PUK를 입력합니다."</string>
<string name="needPuk" msgid="919668385956251611">"SIM 카드의 PUK가 잠겨 있습니다. 잠금해제하려면 PUK 코드를 입력하세요."</string>
<string name="needPuk2" msgid="4526033371987193070">"SIM 카드 잠금을 해제하려면 PUK2를 입력하세요."</string>
<string name="ClipMmi" msgid="6952821216480289285">"발신자 번호"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"비행기 모드"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"비행기 모드 사용"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"비행기 모드 사용 안함"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"요금이 부과되는 서비스"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"애플리케이션이 SMS 메시지를 받고 처리할 수 있도록 합니다. 이 경우 악성 애플리케이션이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMS 수신"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"애플리케이션이 MMS 메시지를 받고 처리할 수 있도록 합니다. 이 경우 악성 애플리케이션이 메시지를 모니터링하거나 사용자가 보기 전에 삭제할 수 있습니다."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"긴급 방송 수신"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"애플리케이션이 긴급 방송 메시지를 수신하고 처리할 수 있도록 합니다. 이 권한은 시스템 애플리케이션에만 사용할 수 있습니다."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"SMS 메시지 보내기"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"애플리케이션이 SMS 메시지를 보낼 수 있도록 합니다. 이 경우 악성 애플리케이션이 사용자의 확인 없이 메시지를 전송하여 요금을 부과할 수 있습니다."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMS 또는 MMS 읽기"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"애플리케이션이 포그라운드에 있는 활동을 강제로 닫고 되돌아갈 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
<string name="permlab_dump" msgid="1681799862438954752">"시스템 내부 상태 검색"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"애플리케이션이 시스템의 내부 상태를 검색할 수 있도록 합니다. 단, 악성 애플리케이션이 이 기능을 이용하여 일반적으로 필요하지 않은 다양한 개인정보와 보안정보를 검색할 수 있습니다."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"화면 콘텐츠 검색"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"애플리케이션이 활성 창의 콘텐츠를 검색할 수 있도록 합니다. 악성 애플리케이션이 전체 창의 콘텐츠를 검색하여 비밀번호를 제외한 모든 텍스트를 조사할 수 있습니다."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"부분 종료"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"보유자가 기기 관리자에게 인텐트를 보낼 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"화면 방향 변경"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"애플리케이션이 언제든지 화면 회전을 변경할 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"포인터 속도 변경"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"애플리케이션이 언제든지 마우스 또는 트랙패드 포인터의 속도를 변경할 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"애플리케이션에 Linux 시그널 보내기"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"애플리케이션이 제공된 시그널을 모든 영구 프로세스로 보내도록 요청할 수 있도록 합니다."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"애플리케이션이 항상 실행되도록 설정"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"연락처 데이터 작성"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"애플리케이션이 태블릿에 저장된 연락처(주소) 데이터를 수정할 수 있도록 합니다. 이 경우 악성 애플리케이션이 연락처 데이터를 지우거나 수정할 수 있습니다."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"애플리케이션이 휴대전화에 저장된 연락처(주소) 데이터를 수정할 수 있도록 합니다. 이 경우 악성 애플리케이션이 연락처 데이터를 지우거나 수정할 수 있습니다."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"캘린더 일정 읽기"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"애플리케이션이 태블릿에 저장된 모든 캘린더 일정을 읽을 수 있도록 합니다. 이 경우 악성 애플리케이션이 캘린더 일정을 다른 사람에게 보낼 수 있습니다."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"애플리케이션이 휴대전화에 저장된 모든 캘린더 일정을 읽을 수 있도록 합니다. 이 경우 악성 애플리케이션이 캘린더 일정을 다른 사람에게 보낼 수 있습니다."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"NFC(Near Field Communication) 제어"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"애플리케이션에서 NFC(Near Field Communication) 태그, 카드 및 리더와 통신할 수 있습니다."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"모든 네트워크 트래픽을 가로채고 수정"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"VPN 연결 설정과 같은 작업을 수행하기 위해 애플리케이션이 모든 네트워크 트래픽을 가로채고 검사하도록 허용합니다. 사용자 몰래 악성 애플리케이션이 네트워크 패킷을 모니터링, 리디렉션 또는 수정할 수 있습니다."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"애플리케이션이 모든 네트워크 트래픽을 가로채서 검사하여 VPN 연결을 설정하도록 허용합니다. 사용자 몰래 악성 애플리케이션이 네트워크 패킷을 모니터링, 리디렉션 또는 수정할 수 있습니다."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"키 잠금 사용 중지"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"애플리케이션이 키 잠금 및 관련 비밀번호 보안을 사용 중지할 수 있도록 합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용 중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"애플리케이션이 캐시 파일시스템을 읽고 쓸 수 있도록 합니다."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"인터넷 전화 걸기/받기"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"애플리케이션에서 SIP 서비스를 사용하여 인터넷 전화를 걸거나 받을 수 있습니다."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"화면 잠금 비밀번호 변경 빈도 설정"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"저장소 암호화 설정"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"저장한 애플리케이션 데이터를 암호화해야 합니다."</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"집"</item>
<item msgid="869923650527136615">"모바일"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"직장"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"기타"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN 코드 입력"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"PUK 및 새 PIN 코드 입력"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 코드"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"새 PIN 코드"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"비밀번호를 입력하려면 터치하세요."</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"잠금을 해제하려면 비밀번호 입력"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"잠금을 해제하려면 PIN 입력"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"태블릿에 SIM 카드가 없습니다."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"휴대전화에 SIM 카드가 없습니다."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"SIM 카드를 삽입하세요."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB 저장소를 사용하면 사용 중인 일부 애플리케이션이 중지되어 USB 저장소를 사용 중지할 때까지 사용할 수 없게 됩니다."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB 작업 실패"</string>
<string name="dlg_ok" msgid="7376953167039865701">"확인"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB 저장소를 포맷하여 저장된 파일을 모두 지우시겠습니까? 수행한 후에는 작업을 취소할 수 없습니다."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"L2TP(Layer 2 Tunneling Protocol)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"사전 공유 키 기반 L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"인증서 기반 L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"파일 선택"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string>
<string name="reset" msgid="2448168080964209908">"초기화"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"내부 저장공간"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD 카드"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB 저장소"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"수정..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"보안 인증서"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"유효한 인증서입니다."</string>
+ <string name="issued_to" msgid="9032338008819841339">"발급 대상:"</string>
+ <string name="common_name" msgid="5745530093500062357">"일반 이름:"</string>
+ <string name="org_name" msgid="8868889052889991293">"조직:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"조직 구성 단위:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"발급 기관:"</string>
+ <string name="validity_period" msgid="57988851973181309">"유효성:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"발급 날짜:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"만료 날짜:"</string>
</resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index dbaad13..ec2313c 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -31,5 +31,14 @@
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height">40dip</dimen>
+ <!-- Vertical padding around action bar icons. -->
+ <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+ <!-- Text size for action bar titles -->
+ <dimen name="action_bar_title_text_size">16dp</dimen>
+ <!-- Text size for action bar subtitles -->
+ <dimen name="action_bar_subtitle_text_size">12dp</dimen>
+
+ <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
+ <dimen name="keyguard_lockscreen_clock_font_size">70sp</dimen>
</resources>
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
index 55eb145..4f49135 100644
--- a/core/res/res/values-large/dimens.xml
+++ b/core/res/res/values-large/dimens.xml
@@ -43,10 +43,4 @@
<!-- Preference UI dimensions for larger screens. -->
<dimen name="preference_widget_width">56dp</dimen>
- <!-- The maximum number of action buttons that should be permitted within
- an action bar/action mode. This will be used to determine how many
- showAsAction="ifRoom" items can fit. "always" items can override this. -->
- <integer name="max_action_buttons">5</integer>
- <!-- Default height of an action bar. -->
- <dimen name="action_bar_default_height">56dip</dimen>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index eab92c6..d99d0ec 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Įvestas PUK kodas neteisingas."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Įvesti PIN kodai neatitinka."</string>
<string name="invalidPin" msgid="3850018445187475377">"Įveskite PIN kodą, sudarytą iš 4–8 skaičių."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Įveskite 8 skaitmenų ar ilgesnį PUK kodą."</string>
<string name="needPuk" msgid="919668385956251611">"Jūsų SIM kortelė yra užrakinta PUK kodu. Jei norite ją atrakinti, įveskite PUK kodą."</string>
<string name="needPuk2" msgid="4526033371987193070">"Įveskite PUK2 kodą, kad panaikintumėte SIM kortelės blokavimą."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Įeinančio skambintojo ID"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lėktuvo režimas"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ĮJUNGTAS lėktuvo režimas"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"lėktuvo režimas IŠJUNGTAS"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
<string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Paslaugos, už kurias mokėjote"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Leidžia programai gauti ir apdoroti SMS pranešimus. Kenkėjiškos programos gali stebėti jūsų pranešimus arba ištrinti juos neparodžiusios jums."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"gauti MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Leidžia programai gauti ir apdoroti MMS pranešimus. Kenkėjiškos programos gali stebėti jūsų pranešimus arba ištrinti juos neparodžiusios jums."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"gauti kritinės padėties transliacijas"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Leidžiama programa gauti ir apdoroti kritinės padėties transliacijos pranešimus. Šis leidimas galimas tik naudojant sistemos programas."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"siųsti SMS pranešimus"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Leidžia programai siųsti SMS pranešimus. Kenkėjiškos programos gali kainuoti jums pinigų, nes gali siųsti SMS pranešimus be jūsų patvirtinimo."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"skaityti SMS ar MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Leidžia programai uždaryti bet kurią aktyviojo lango veiklą ir eiti atgal. Niekada neturėtų būti reikalinga įprastose programose."</string>
<string name="permlab_dump" msgid="1681799862438954752">"nuskaityti sistemos vidinę būseną"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Leidžia programai nuskaityti vidinę sistemos būseną. Kenkėjiškos programos gali nuskaityti įvairią privačią ir saugią informaciją, kurios įprastai joms nereikia."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"nuskaityti ekrano turinį"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Leidžiama programa nuskaityti aktyvaus lango turinį. Kenkėjiškomis programomis gali būti nuskaitytas visas lango turinys ir išnagrinėtas visas jo tekstas, išskyrus slaptažodžius."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"dalinis išjungimas"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Veiklos tvarkyklę perjungia į išsijungimo būseną. Neišjungia visiškai."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Leidžia savininkui siųsti tikslus įrenginio administratoriui. Neturėtų reikėti įprastose programose."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"keisti ekrano padėtį"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Leidžia programai bet kuriuo metu keisti ekrano sukimą. Neturėtų reikėti įprastoms programoms."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"keisti žymiklio greitį"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Galima programa bet kuriuo metu pakeisti pelės ar jutiklinės planšetės žymiklio greitį. Nereikalingas naudojant įprastas programas."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"programoms siųsti „Linux“ signalus"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Leidžia programai pateikti užklausą, kad teikiamas signalas būtų siunčiamas visiems nuolatiniams procesams."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"nustatyti, kad programa būtų visada paleista"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"rašyti adresatų duomenis"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Leidžiama programai keisti kontaktų (adreso) duomenis, išsaugotus planšetiniame kompiuteryje. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų kontaktų duomenis."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Leidžia programai keisti adresatų (adresų) duomenis, išsaugotus jūsų telefone. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar pakeistų jūsų adresatų duomenis."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"skaityti kalendoriaus įvykius"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Leidžiama programai skaityti visus kalendoriaus įvykius, išsaugotus jūsų planšetiniame kompiuteryje. Kenkėjiškos programos gali tai naudoti, kad siųstų jūsų kalendoriaus įvykius kitiems žmonėms."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Leidžia programai skaityti visus kalendoriaus įvykius, išsaugotus jūsų telefone. Kenkėjiškos programos tai gali naudoti, kad siųstų kalendoriaus įvykius kitiems žmonėms."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Leidžiama programai perduoti artimo lauko perdavimo (angl. „Near Field Communication“, NFC) žymas, korteles ir skaitymo programas."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"perimti ir pakeisti visą tinklo srautą"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Leidžiama programai perimti ir tirti visą tinklo srautą, pavyzdžiui, kad būtų galima užmegzti VPN ryšį. Kenkėjiškos programos gali be jūsų žinios stebėti, peradresuoti ar keisti tinklo paketus."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Leidžiama programai perimti ir tirti visą tinklo duomenų srautą, kad būtų galima užmegzti VPN ryšį. Kenkėjiškos programos gali be jūsų žinios stebėti, peradresuoti ar keisti tinklo paketus."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"išjungti užraktą"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Leidžia programai išjungti užraktą ir visą susijusią slaptažodžio apsaugą. Patikimas pavyzdys būtų užrakto išjungimas telefone gaunant įeinantį skambutį ir įgalinant jį vėl, kai skambutis baigtas."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"skaityti sinchronizavimo nustatymus"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Leidžia programai skaityti ir rašyti į talpyklos failų sistemą."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"skambinti / priimti skambučius internetu"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Leidžiama programai naudoti SIP paslaugą norint skambinti / priimti skambučius internetu."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir juose leidžiamus naudoti simbolius"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Valdykite, kaip dažnai reikia keisti ekrano užrakto slaptažodį"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nustatyti atmintinės šifruotę"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Saugomos programos duomenys turi būti šifruoti"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Pagrindinis"</item>
<item msgid="869923650527136615">"Mobilusis"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbas"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Kita"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Įveskite PIN kodą"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Įveskite PUK ir naują PIN kodus"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kodas"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Naujas PIN kodas"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Kad įvest. slaptaž., paliesk."</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Įveskite slaptažodį, kad atrakintumėte"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Jei norite atrakinti, įveskite PIN kodą"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefone nėra SIM kortelės."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Įdėkite SIM kortelę."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Tik pagalbos skambučiai"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Tinklas užrakintas"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kortelė užrakinta PUK kodu."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jei įjungiate USB saugyklą, kai kurios naudojamos programos sustos ir gali būti negalimos, kol išjungsite USB saugyklą."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB operacija nepavyko"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Gerai"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB atmint."</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuoti SD kortelę"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatuoti USB atmintinę ištrinant visus joje saugomus failus? Veiksmo nebus galima atšaukti!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"2 sluoksnio tunelinis protokolas"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Iš anksto bendrinamas raktas, pagrįstas L2TP/IPSec VPT"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikatas pagrįstas L2TP/IPSec VPT"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
<string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Vidinė atmintis"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD kortelė"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB atmintis"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Redaguoti..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Saugos sertifikatas"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Šis sertifikatas galioja."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Išduota:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Bendras pavadinimas:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizacija:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizacinis vienetas:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Išdavė:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Galiojimas:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Išduota:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Galiojimas baigiasi:"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5c5525c..553f3ee 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Ierakstītais PUK kods nav pareizs."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Ievadītie PIN neatbilst."</string>
<string name="invalidPin" msgid="3850018445187475377">"Ierakstiet PIN, kas sastāv no 4 līdz 8 cipariem."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Ierakstiet PUK kodu, kas sastāv no 8 vai vairāk cipariem."</string>
<string name="needPuk" msgid="919668385956251611">"SIM karte ir bloķēta ar PUK kodu. Ierakstiet PUK kodu, lai to atbloķētu."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ierakstiet PUK2 kodu, lai atbloķētu SIM karti."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Ienākošā zvana zvanītāja ID"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lidojuma režīms"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lidojuma režīms ir IESLĒGTS."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lidojuma režīms ir IZSLĒGTS."</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksas pakalpojumi"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Ļauj lietojumprogrammai saņemt un apstrādāt īsziņas. Ļaunprātīgas lietojumprogrammas var pārraudzīt jūsu ziņojumus vai dzēst tos, neparādot tos jums."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"saņemt multiziņu"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Ļauj lietojumprogrammai saņemt un apstrādāt multiziņas. Ļaunprātīgas lietojumprogrammas var pārraudzīt jūsu ziņojumus vai dzēst tos, neparādot tos jums."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"Ārkārtas apraižu saņemšana"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Ļauj lietojumprogrammai saņemt un apstrādāt ārkārtas apraides ziņojumus. Šī atļauja attiecas tikai uz sistēmas lietojumprogrammām."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"sūtīt īsziņas"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Ļauj lietojumprogrammai sūtīt īsziņas. Ļaunprātīgas lietojumprogrammas var radīt jums izmaksas, bez apstiprinājuma sūtot īsziņas."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"lasīt īsziņu vai multiziņu"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Ļauj lietojumprogrammai aizvērt jebkuru priekšplānā esošu darbību un atgriezties atpakaļ. Parastajās lietojumprogrammās nekad nav nepieciešams."</string>
<string name="permlab_dump" msgid="1681799862438954752">"izgūt sistēmas iekšējo stāvokli"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Ļauj lietojumprogrammai izgūt sistēmas iekšējo stāvokli. Ļaunprātīgas lietojumprogrammas var izgūt plašu privātās un drošās informācijas spektru, kas tai parasti nav nepieciešama."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Ekrāna satura iegūšana"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Ļauj lietojumprogrammai piekļūt aktīva loga saturam. Ļaunprātīgas lietojumprogrammas var iegūt visu loga saturu un pārbaudīt visu tekstu, izņemot paroles."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"daļēja izslēgšana"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Liek darbību pārvaldniekam pāriet izslēgšanas stāvoklī. Neveic pilnīgu izslēgšanu."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Ļauj īpašniekam sūtīt nolūkus ierīces administratoram. Nekad nav nepieciešams parastajām lietojumprogrammām."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mainīt ekrāna orientāciju"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Ļauj lietojumprogrammai jebkurā brīdī mainīt ekrāna pagriešanas iestatījumu. Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Rādītāja ātruma mainīšana"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Ļauj lietojumprogrammai jebkurā laikā mainīt peles vai skārienpaliktņa rādītāja ātrumu. Parastās lietojumprogrammās šī funkcija nav nepieciešama."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"sūtīt Linux signālus uz lietojumprogrammām"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Ļauj lietojumprogrammai pieprasīt, lai piegādātais signāls tiktu sūtīts uz visiem pastāvīgajiem procesiem."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"likt lietojumprogrammai vienmēr darboties"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"rakstīt kontaktpersonu datus"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ļauj lietojumprogrammai pārveidot planšetdatorā saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ļauj lietojumprogrammai pārveidot tālrunī saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"lasīt kalendāra pasākumus"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ļauj lietojumprogrammai lasīt visus planšetdatorā saglabātos kalendāra notikumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu kalendāra notikumus citām personām."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ļauj lietojumprogrammai lasīt visus tālrunī saglabātos kalendāra pasākumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu kalendāra pasākumus citām personām."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontrolē tuvlauka saziņu"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Ļauj lietojumprogrammai sazināties ar tuvlauka saziņas (Near Field Communication — NFC) atzīmēm, kartēm un lasītājiem."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"pārtvert un pārveidot visu tīkla datplūsmu"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Ļauj lietojumprogrammai pārtvert un pārbaudīt visu tīkla datplūsmu, lai, piemēram, izveidotu VPN savienojumu. Ļaunprātīgas lietojumprogrammas var pārraudzīt, novirzīt vai pārveidot tīkla paketes, jums nezinot."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Ļauj lietojumprogrammai pārtvert un pārbaudīt visu tīkla datplūsmu, lai izveidotu VPN savienojumu. Ļaunprātīgas lietojumprogrammas var pārraudzīt, novirzīt vai pārveidot tīkla paketes, jums nezinot."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"atspējot atslēgas slēgu"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ļauj lietojumprogrammai atspējot atslēgas slēgu un jebkādu saistīto paroles drošību. Atbilstošs tā piemērs: tālrunis atspējo atslēgas slēgu, saņemot ienākošu tālruņa zvanu, pēc tam atkārtoti iespējo atslēgas slēgu, kad saruna ir pabeigta."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lasīt sinhronizācijas iestatījumus"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Ļauj lietojumprogrammai lasīt kešatmiņas failu sistēmu un rakstīt tajā."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"veikt/saņemt interneta zvanus"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Ļauj lietojumprogrammai izmantot SIP pakalpojumu, vai veiktu/saņemtu interneta zvanus."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolē, cik bieži ir jāmaina ekrāna bloķēšanas parole."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Skatīt atmiņas šifrējumu"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Pieprasīt, lai saglabātie lietojumprogrammas dati tiktu šifrēti"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Mājas"</item>
<item msgid="869923650527136615">"Mobilais"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbs"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Cits"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ievadiet PIN kodu"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Ievadiet PUK kodu un jaunu PIN kodu."</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kods"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Jauns PIN kods"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Pieskarieties, lai ievadītu paroli"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Lai atbloķētu, ievadiet paroli."</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Lai atbloķētu, ievadiet PIN"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetdatorā nav SIM kartes."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tālrunī nav SIM kartes."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Lūdzu, ievietojiet SIM karti."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Tikai ārkārtas zvani"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Tīkls ir bloķēts."</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM karte ir bloķēta ar PUK kodu."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ja ieslēgsiet USB krātuvi, dažu joprojām lietoto lietojumprogrammu darbība tiks apturēta un tās, iespējams, nebūs pieejamas līdz brīdim, kad USB krātuve tiks izslēgta."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB darbība neizdevās."</string>
<string name="dlg_ok" msgid="7376953167039865701">"Labi"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB kr. formatēšana"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartes formatēšana"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vai formatēt USB krātuvi, dzēšot visus tajā saglabātos failus? Šo darbību nevar atcelt."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"2. slāņa tunelēšanas protokols"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Uz iepriekš koplietotas atslēgas balstīts L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Uz sertifikātu balstīts L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string>
<string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Iekšējā atmiņa"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD karte"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB atmiņa"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediģēt..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Drošības sertifikāts"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikāts ir derīgs."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Izdots:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Kopējais nosaukums:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizācija:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizācijas vienība:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Izsniedzējs:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Derīgums:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Izsniegšanas datums:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Derīguma termiņš:"</string>
</resources>
diff --git a/core/res/res/values-ms-rMY/arrays.xml b/core/res/res/values-ms-rMY/arrays.xml
new file mode 100644
index 0000000..3a708e6
--- /dev/null
+++ b/core/res/res/values-ms-rMY/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>4210484</item>
+ <item>101975766</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6b0e18e..f432672 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -34,8 +34,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Mel suara"</string>
<string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
<string name="mmiError" msgid="5154499457739052907">"Masalah sambungan atau kod MMI tidak sah"</string>
- <!-- no translation found for mmiFdnError (5224398216385316471) -->
- <skip />
+ <string name="mmiFdnError" msgid="5224398216385316471">"Pengendalian dihadkan kepada nombor dailan tetap sahaja."</string>
<string name="serviceEnabled" msgid="8147278346414714315">"Perkhidmatan telah didayakan."</string>
<string name="serviceEnabledFor" msgid="6856228140453471041">"Perkhidmatan didayakan untuk:"</string>
<string name="serviceDisabled" msgid="1937553226592516411">"Perkhidmatan telah dilumpuhkan."</string>
@@ -47,6 +46,8 @@
<string name="badPuk" msgid="5702522162746042460">"Kod PUK yang anda taipkan tidak betul."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN yang anda masukkan tidak sepadan."</string>
<string name="invalidPin" msgid="3850018445187475377">"Taipkan PIN yang mengandungi 4 hingga 8 nombor."</string>
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"Kad SIM anda dikunci PUK. Taipkan kod PUK untuk membuka kuncinya."</string>
<string name="needPuk2" msgid="4526033371987193070">"Taipkan PUK2 untuk menyahsekat kad SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID Pemanggil Masuk"</string>
@@ -71,18 +72,12 @@
<string name="RestrictedChangedTitle" msgid="5592189398956187498">"Akses terhad diubah"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"Perkhidmatan data disekat."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"Perkhidmatan kecemasan disekat."</string>
- <!-- no translation found for RestrictedOnNormal (4953867011389750673) -->
- <skip />
- <!-- no translation found for RestrictedOnAllVoice (1459318899842232234) -->
- <skip />
- <!-- no translation found for RestrictedOnSms (8314352327461638897) -->
- <skip />
- <!-- no translation found for RestrictedOnVoiceData (8244438624660371717) -->
- <skip />
- <!-- no translation found for RestrictedOnVoiceSms (1888588152792023873) -->
- <skip />
- <!-- no translation found for RestrictedOnAll (2714924667937117304) -->
- <skip />
+ <string name="RestrictedOnNormal" msgid="4953867011389750673">"Perkhidmatan suara disekat."</string>
+ <string name="RestrictedOnAllVoice" msgid="1459318899842232234">"Semua perkhidmatan Suara disekat."</string>
+ <string name="RestrictedOnSms" msgid="8314352327461638897">"Perkhidmatan SMS disekat."</string>
+ <string name="RestrictedOnVoiceData" msgid="8244438624660371717">"Perkhidmatan suara/data disekat."</string>
+ <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Perkhidmatan suara/SMS disekat."</string>
+ <string name="RestrictedOnAll" msgid="2714924667937117304">"Semua perkhidmatan Suara/Data/SMS disekat."</string>
<string name="serviceClassVoice" msgid="1258393812335258019">"Suara"</string>
<string name="serviceClassData" msgid="872456782077937893">"Data"</string>
<string name="serviceClassFAX" msgid="5566624998840486475">"FAKS"</string>
@@ -128,15 +123,14 @@
<string name="httpErrorFile" msgid="8250549644091165175">"Fail tidak boleh diakses."</string>
<string name="httpErrorFileNotFound" msgid="5588380756326017105">"Fail yang diminta tidak ditemui."</string>
<string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Terlalu banyak permintaan sedang diproses. Cuba sebentar lagi."</string>
- <!-- no translation found for notification_title (1259940370369187045) -->
- <skip />
+ <string name="notification_title" msgid="1259940370369187045">"Ralat log masuk untuk <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"Penyegerakan"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Penyegerakan"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak pemadaman <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
- <!-- outdated translation 6632412458436461203 --> <string name="low_memory" product="tablet" msgid="2292820184396262278">"Storan telefon penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Storan tablet penuh! Padamkan beberapa fail untuk mengosongkan ruang."</string>
<string name="low_memory" product="default" msgid="6632412458436461203">"Storan telefon penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
<string name="me" msgid="6545696007631404292">"Saya"</string>
- <!-- outdated translation 1319919075463988638 --> <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Pilihan telefon"</string>
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Pilihan tablet"</string>
<string name="power_dialog" product="default" msgid="1319919075463988638">"Pilihan telefon"</string>
<string name="silent_mode" msgid="7167703389802618663">"Mod senyap"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Hidupkan wayarles"</string>
@@ -144,14 +138,12 @@
<string name="screen_lock" msgid="799094655496098153">"Kunci skrin"</string>
<string name="power_off" msgid="4266614107412865048">"Matikan kuasa"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Mematikan..."</string>
- <!-- outdated translation 649792175242821353 --> <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Telefon anda akan dimatikan."</string>
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet anda akan dimatikan."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon anda akan dimatikan."</string>
- <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
- <skip />
- <!-- no translation found for recent_tasks_title (3691764623638127888) -->
- <skip />
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"Adakah anda mahu menutup?"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"Baru-baru ini"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"Tiada aplikasi terbaru."</string>
- <!-- outdated translation 2406416831541615258 --> <string name="global_actions" product="tablet" msgid="408477140088053665">"Pilihan telefon"</string>
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Pilihan tablet"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Pilihan telefon"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Kunci skrin"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Matikan kuasa"</string>
@@ -161,8 +153,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod pesawat"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mod Pesawat DIHIDUPKAN"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mod Pesawat DIMATIKAN"</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
- <skip />
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string>
@@ -170,16 +161,14 @@
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string>
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Membaca dan menulis SMS, e-mel dan mesej lain."</string>
<string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Maklumat peribadi anda"</string>
- <!-- outdated translation 5488050357388806068 --> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung kepada kenalan dan kalendar yang disimpan pada telefon."</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung kepada kenalan dan kalendar anda yang disimpan dalam tablet."</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Akses langsung kepada kenalan dan kalendar yang disimpan pada telefon."</string>
<string name="permgrouplab_location" msgid="635149742436692049">"Lokasi anda"</string>
<string name="permgroupdesc_location" msgid="2430258821648348660">"Pantau lokasi fizikal anda"</string>
<string name="permgrouplab_network" msgid="5808983377727109831">"Komunikasi rangkaian"</string>
<string name="permgroupdesc_network" msgid="5035763698958415998">"Membenarkan aplikasi mengakses pelbagai ciri rangkaian"</string>
- <!-- no translation found for permgrouplab_accounts (3359646291125325519) -->
- <skip />
- <!-- no translation found for permgroupdesc_accounts (4948732641827091312) -->
- <skip />
+ <string name="permgrouplab_accounts" msgid="3359646291125325519">"Akaun anda"</string>
+ <string name="permgroupdesc_accounts" msgid="4948732641827091312">"Akses akaun yang tersedia."</string>
<string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"Kawalan perkakasan"</string>
<string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"Akses langsung kepada perkakasan pada set tangan."</string>
<string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"Panggilan telefon"</string>
@@ -189,14 +178,12 @@
<string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Alatan pembangunan"</string>
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Ciri hanya diperlukan untuk pembangun aplikasi."</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Storan"</string>
- <!-- outdated translation 9203302214915355774 --> <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses kad SD."</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses storan USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Akses kad SD."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"lumpuhkan atau ubah suai bar status"</string>
<string name="permdesc_statusBar" msgid="1365473595331989732">"Membenarkan aplikasi melumpuhkan bar status atau menambah dan mengalih keluar ikon sistem."</string>
- <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
- <skip />
- <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
- <skip />
+ <string name="permlab_statusBarService" msgid="7247281911387931485">"bar status"</string>
+ <string name="permdesc_statusBarService" msgid="4097605867643520920">"Membenarkan aplikasi menjadi bar status."</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"kembangkan/runtuhkan bar status"</string>
<string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Membenarkan aplikasi mengembangkan atau meruntuhkan bar status."</string>
<string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"sekat panggilan keluar"</string>
@@ -205,13 +192,17 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Membolehkan aplikasi untuk menerima dan memproses mesej SMS. aplikasi berbahaya boleh memantau mesej atau memadamkannya tanpa menunjukkan kepada anda."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"terima MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Membenarkan aplikasi menerima dan memproses mesej MMS. Aplikasi berniat jahat mungkin memantau mesej anda atau memadamkannya tanpa menunjukkan kepada anda."</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<string name="permlab_sendSms" msgid="5600830612147671529">"hantar mesej SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Membolehkan aplikasi menghantar mesej SMS. Aplikasi berniat jahat boleh merugikan wang anda dengan menghantar mesej tanpa pengesahan anda."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"baca SMS atau MMS"</string>
- <!-- outdated translation 3002170087197294591 --> <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Membenarkan aplikasi membaca mesej SMS yang disimpan pada telefon atau kad SIM anda. Aplikasi berniat jahat boleh membaca mesej sulit anda."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Membenarkan aplikasi membaca mesej SMS yang disimpan pada tablet atau kad SIM anda. Aplikasi berniat jahat boleh membaca mesej sulit anda."</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Membenarkan aplikasi membaca mesej SMS yang disimpan pada telefon atau kad SIM anda. Aplikasi berniat jahat boleh membaca mesej sulit anda."</string>
<string name="permlab_writeSms" msgid="6881122575154940744">"edit SMS atau MMS"</string>
- <!-- outdated translation 6299398896177548095 --> <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Membolehkan aplikasi untuk menulis mesej SMS yang disimpan pada telefon anda atau kad SIM. Aplikasi berbahaya boleh memadamkan mesej anda."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Membenarkan aplikasi menulis mesej SMS yang disimpan pada tablet atau kad SIM anda. Aplikasi berniat jahat boleh memadamkan mesej anda."</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Membolehkan aplikasi untuk menulis mesej SMS yang disimpan pada telefon anda atau kad SIM. Aplikasi berbahaya boleh memadamkan mesej anda."</string>
<string name="permlab_receiveWapPush" msgid="8258226427716551388">"terima WAP"</string>
<string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Membenarkan aplikasi menerima dan memproses mesej WAP. Aplikasi berniat jahat mungkin memantau mesej anda atau memadamnya tanpa menunjukkan kepada anda."</string>
@@ -219,36 +210,32 @@
<string name="permdesc_getTasks" msgid="7048711358713443341">"Membenarkan aplikasi mengambil semula maklumat mengenai tugasan terbaru dan tugasan semasa yang dijalankan. Boleh membenarkan aplikasi berniat jahat menemui maklumat peribadi mengenai aplikasi lain."</string>
<string name="permlab_reorderTasks" msgid="5669588525059921549">"susun semula tertib aplikasi yang dijalankan"</string>
<string name="permdesc_reorderTasks" msgid="126252774270522835">"Membenarkan aplikasi mengalih tugas ke latar depan dan latar belakang. Aplikasi berniat jahat boleh memaksa dirinya ke depan tanpa kawalan anda."</string>
- <!-- no translation found for permlab_removeTasks (4802740047161700683) -->
- <skip />
- <!-- no translation found for permdesc_removeTasks (2000332928514575461) -->
- <skip />
+ <string name="permlab_removeTasks" msgid="4802740047161700683">"hentikan aplikasi yang sedang dijalankan"</string>
+ <string name="permdesc_removeTasks" msgid="2000332928514575461">"Membenarkan aplikasi mengalih keluar tugasan dan membunuh aplikasinya. Aplikasi berniat jahat boleh mengganggu tingkah laku aplikasi lain."</string>
<string name="permlab_setDebugApp" msgid="4339730312925176742">"dayakan penyahpepijatan aplikasi"</string>
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"Membenarkan aplikasi menghidupkan penyahpepijatan untuk aplikasi lain. Aplikasi berniat jahat boleh menggunakannya untuk membunuh aplikasi lain."</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"tukar tetapan UI anda"</string>
<string name="permdesc_changeConfiguration" msgid="3465121501528064399">"Membenarkan aplikasi mengubah konfigurasi semasa seperti tempat peristiwa atau saiz fon keseluruhan."</string>
- <!-- no translation found for permlab_enableCarMode (5684504058192921098) -->
- <skip />
- <!-- no translation found for permdesc_enableCarMode (5673461159384850628) -->
- <skip />
- <!-- no translation found for permlab_killBackgroundProcesses (8373714752793061963) -->
- <skip />
- <!-- no translation found for permdesc_killBackgroundProcesses (2908829602869383753) -->
- <skip />
- <!-- no translation found for permlab_forceStopPackages (1447830113260156236) -->
- <skip />
- <!-- no translation found for permdesc_forceStopPackages (7263036616161367402) -->
- <skip />
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"dayakan mod kereta"</string>
+ <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Membenarkan aplikasi mendayakan mod kereta."</string>
+ <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"bunuh proses latar belakang"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Membenarkan aplikasi membunuh proses latar belakang aplikasi lain, walaupun jika memori tidak rendah."</string>
+ <string name="permlab_forceStopPackages" msgid="1447830113260156236">"henti paksa aplikasi lain"</string>
+ <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Membenarkan aplikasi menghentikan aplikasi lain secara paksa."</string>
<string name="permlab_forceBack" msgid="1804196839880393631">"memaksa aplikasi untuk menutup"</string>
<string name="permdesc_forceBack" msgid="6534109744159919013">"Membenarkan aplikasi memaksa sebarang aktiviti dalam latar depan untuk ditutup dan pergi ke belakang. Seharusnya tidak diperlukan untuk aplikasi nomal."</string>
<string name="permlab_dump" msgid="1681799862438954752">"mendapatkan semula keadaan dalaman sistem"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Membenarkan aplikasi mendapatkan semula keadaan dalaman sistem. Aplikasi berniat jahat boleh mendapatkan semula pelbagai maklumat sulit dan dilindungi yang ia tidak seharusnya memerlukannya."</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Menghalang pengguna daripada bertukar kepada aplikasi lain."</string>
<string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"pantau dan kawal semua pelancaran aplikasi"</string>
- <!-- outdated translation 3228701938345388092 --> <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Membenarkan aplikasi memantau dan mengawal cara sistem melancarkan aktiviti. Aplikasi berniat jahat boleh menjejaskan sistem keseluruhannya. Kebenaran ini diperlukan untuk pembangunan sahaja, tidak sekali-kali untuk kegunaan telefon yang biasa."</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Membenarkan aplikasi memantau dan mengawal cara sistem melancarkan aktiviti. Aplikasi berniat jahat boleh menjejaskan sistem keseluruhannya. Kebenaran ini diperlukan untuk pembangunan sahaja, tidak sekali-kali untuk kegunaan biasa."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"hantar siaran bahawa pakej telah dialih keluar"</string>
<string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Membenarkan aplikasi menyiarkan pemberitahuan bahawa pakej aplikasi telah dialih keluar. Aplikasi berniat jahat boleh menggunakannya untuk membunuh sebarang aplikasi lain yang sedang dijalankan."</string>
<string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"hantar siaran SMS diterima"</string>
@@ -262,8 +249,7 @@
<string name="permlab_batteryStats" msgid="7863923071360031652">"ubah suai statistik bateri"</string>
<string name="permdesc_batteryStats" msgid="5847319823772230560">"Membenarkan pengubahsuaian statistik bateri yang dikumpulkan. Bukan untuk kegunaan biasa aplikasi."</string>
<string name="permlab_backup" msgid="470013022865453920">"sandaran dan pemulihan sistem kawalan"</string>
- <!-- no translation found for permdesc_backup (4837493065154256525) -->
- <skip />
+ <string name="permdesc_backup" msgid="4837493065154256525">"Membenarkan aplikasi mengawal mekanisme sandaran dan pemulihan sistem. Bukan untuk kegunaan aplikasi biasa."</string>
<!-- no translation found for permlab_confirm_full_backup (5557071325804469102) -->
<skip />
<!-- no translation found for permdesc_confirm_full_backup (9005017754175897954) -->
@@ -271,30 +257,24 @@
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"memapaparkan tetingkap yang tiada kebenaran"</string>
<string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Membenarkan pewujudan tetingkap yang dimaksudkan untuk digunakan oleh antara muka pengguna sistem dalaman. Bukan untuk kegunaan oleh aplikasi biasa."</string>
<string name="permlab_systemAlertWindow" msgid="3372321942941168324">"paparkan amaran peringkat sistem"</string>
- <!-- outdated translation 5109622689323490558 --> <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Membenarkan aplikasi menunjukkan tetingkap amaran sistem. Aplikasi berniat jahat boleh mengambil alih keseluruhan skrin telefon."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Membenarkan aplikasi menunjukkan tetingkap amaran sistem. Aplikasi berniat jahat boleh mengambil alih keseluruhan skrin."</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"mengubah suai kelajuan animasi global"</string>
<string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Membenarkan aplikasi menukar kelajuan animasi global (animasi yang lebih laju atau lebih perlahan) pada bila-bila masa sahaja."</string>
<string name="permlab_manageAppTokens" msgid="17124341698093865">"urus token aplikasi"</string>
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Membenarkan aplikasi membuat dan mengurus tokennya sendiri, memintas tertib-Z yang biasa. Seharusnya tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
<string name="permlab_injectEvents" msgid="1378746584023586600">"menekan kekunci dan butang kawalan"</string>
- <!-- outdated translation 3946098050410874715 --> <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Membenarkan aplikasi menyampaikan peristiwa inputnya sendiri (tekanan kekunci, dsb.) pada aplikasi lain. Aplikasi berniat jahat boleh menggunakannya untuk mengambil alih telefon."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Membenarkan aplikasi menyampaikan acara inputnya sendiri (menekan kekunci, dsb.) ke aplikasi lain. Aplikasi berniat jahat boleh menggunakannya untuk mengambil alih tablet."</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Membenarkan aplikasi menyampaikan peristiwa inputnya sendiri (tekanan kekunci, dsb.) pada aplikasi lain. Aplikasi berniat jahat boleh menggunakannya untuk mengambil alih telefon."</string>
<string name="permlab_readInputState" msgid="469428900041249234">"rakam apa yang anda taipkan dan tindakan yang anda ambil"</string>
<string name="permdesc_readInputState" msgid="5132879321450325445">"Membenarkan aplikasi melihat kekunci yang anda tekan walaupun semasa berinteraksi dengan aplikasi lain (seperti memasukkan kata laluan). Seharusnya tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"terikat kepada kaedah input"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kaedah input itu. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
- <!-- no translation found for permlab_bindWallpaper (8716400279937856462) -->
- <skip />
- <!-- no translation found for permdesc_bindWallpaper (5287754520361915347) -->
- <skip />
- <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
- <skip />
- <!-- no translation found for permdesc_bindRemoteViews (2930855984822926963) -->
- <skip />
- <!-- no translation found for permlab_bindDeviceAdmin (8704986163711455010) -->
- <skip />
- <!-- no translation found for permdesc_bindDeviceAdmin (8714424333082216979) -->
- <skip />
+ <string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string>
+ <string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
+ <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
+ <string name="permdesc_bindRemoteViews" msgid="2930855984822926963">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan widget. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
+ <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan pentadbir peranti"</string>
+ <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Membenarkan pemegang menghantar tujuan kepada pentadbir peranti. Tidak sekali-kali diperlukan untuk aplikasi biasa."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"tukar orientasi skrin"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Membolehkan aplikasi untuk menukar putaran skrin pada bila-bila masa. Tidak seharusnya diperlukan untuk aplikasi biasa."</string>
<!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
@@ -316,46 +296,51 @@
<string name="permlab_installPackages" msgid="335800214119051089">"pasang aplikasi secara langsung"</string>
<string name="permdesc_installPackages" msgid="526669220850066132">"Membenarkan aplikasi memasang pakej Android yang baru atau yang dikemas kini. Aplikasi berniat jahat boleh menggunakannya untuk menambah aplikasi dengan sewenang-wenangnya."</string>
<string name="permlab_clearAppCache" msgid="4747698311163766540">"padamkan semua data cache aplikasi"</string>
- <!-- outdated translation 7740465694193671402 --> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Membenarkan aplikasi mengosongkan storan telefon dengan memadamkan fail dalam direktori cache aplikasi. Akses adalah amat terhad dan biasanya kepada proses sistem."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Membenarkan aplikasi mengosongkan storan tablet dengan memadamkan fail dalam direktori cache aplikasi. Akses adalah amat terhad dan biasanya kepada proses sistem."</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Membenarkan aplikasi mengosongkan storan telefon dengan memadamkan fail dalam direktori cache aplikasi. Akses adalah amat terhad dan biasanya kepada proses sistem."</string>
- <!-- no translation found for permlab_movePackage (728454979946503926) -->
- <skip />
- <!-- no translation found for permdesc_movePackage (6323049291923925277) -->
- <skip />
- <!-- outdated translation 4811921703882532070 --> <string name="permlab_readLogs" msgid="6615778543198967614">"baca fail log sistem"</string>
- <!-- outdated translation 2257937955580475902 --> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Membenarkan aplikasi membaca daripada pelbagai fail log sistem. Hal ini membenarkannya menemui maklumat umum mengenai apa yang anda lakukan dengan telefon tetapi ia tidak seharusnya mengandungi sebarang maklumat peribadi atau sulit."</string>
- <!-- outdated translation 2257937955580475902 --> <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Membenarkan aplikasi membaca daripada pelbagai fail log sistem. Hal ini membenarkannya menemui maklumat umum mengenai apa yang anda lakukan dengan telefon tetapi ia tidak seharusnya mengandungi sebarang maklumat peribadi atau sulit."</string>
+ <string name="permlab_movePackage" msgid="728454979946503926">"Alihkan sumber aplikasi"</string>
+ <string name="permdesc_movePackage" msgid="6323049291923925277">"Membenarkan aplikasi untuk mengalihkan sumber aplikasi dari media dalaman ke media luaran dan sebaliknya."</string>
+ <string name="permlab_readLogs" msgid="6615778543198967614">"baca data log sensitif"</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Membenarkan aplikasi membaca daripada pelbagai fail log sistem. Hal ini membenarkannya menemui maklumat umum mengenai perkara yang anda lakukan dengan tablet, juga berpotensi menemui maklumat persendirian dan peribadi."</string>
+ <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Membenarkan aplikasi membaca daripada pelbagai fail log sistem. Hal ini membenarkannya menemui maklumat umum mengenai perkara yang anda lakukan dengan telefon, juga berpotensi menyertakan maklumat persendirian dan peribadi."</string>
<string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber yang dimiliki oleh diag"</string>
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Membenarkan aplikasi membaca dan menulis ke sebarang sumber yang dimiliki oleh kumpulan diag; contohnya, fail dalam /dev. Hal ini berpotensi untuk menjejaskan kestabilan dan keselamatan sistem. Perkara ini harus hanya digunakan untuk diagnosis khusus perkakasan oleh pengilang atau pengendali."</string>
<string name="permlab_changeComponentState" msgid="79425198834329406">"dayakan atau lumpuhkan komponen aplikasi"</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Membenarkan aplikasi menukarkan sama ada komponen aplikasi lain didayakan ataupun tidak. Aplikasi berniat jahat boleh menggunakannya untuk melumpuhkan keupayaan penting telefon. Tindakan berhati-hati harus digunakan dengan kebenaran kerana ia boleh mengakibatkan komponen aplikasi menjadi tidak boleh digunakan, tidak konsisten atau tidak stabil."</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Membenarkan aplikasi menukarkan sama ada komponen aplikasi lain didayakan ataupun tidak. Aplikasi berniat jahat boleh menggunakannya untuk melumpuhkan keupayaan penting telefon. Tindakan berhati-hati harus digunakan dengan kebenaran kerana ia boleh mengakibatkan komponen aplikasi menjadi tidak boleh digunakan, tidak konsisten atau tidak stabil."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Membenarkan aplikasi menukarkan sama ada komponen aplikasi lain didayakan ataupun tidak. Aplikasi berniat jahat boleh menggunakannya untuk melumpuhkan keupayaan penting tablet. Tindakan berhati-hati harus digunakan dengan kebenaran ini kerana ia boleh mengakibatkan komponen aplikasi menjadi tidak boleh digunakan, tidak konsisten atau berada dalam keadaan tidak stabil."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Membenarkan aplikasi menukarkan sama ada komponen aplikasi lain didayakan ataupun tidak. Aplikasi berniat jahat boleh menggunakannya untuk melumpuhkan keupayaan penting telefon. Tindakan berhati-hati harus digunakan dengan kebenaran ini kerana ia boleh mengakibatkan komponen aplikasi menjadi tidak boleh digunakan, tidak konsisten atau berada dalam keadaan tidak stabil."</string>
<string name="permlab_setPreferredApplications" msgid="3393305202145172005">"tetapkan aplikasi keutamaan"</string>
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Membenarkan aplikasi mengubah aplikasi keutamaan anda. Hal ini boleh membenarkan aplikasi berniat jahat mengubah aplikasi yang sedang dijalankan secara senyap-senyap, menipu aplikasi sedia ada bagi mengumpul data peribadi daripada anda."</string>
<string name="permlab_writeSettings" msgid="1365523497395143704">"mengubah suai tetapan sistem global"</string>
<string name="permdesc_writeSettings" msgid="838789419871034696">"Membolehkan aplikasi mengubah suai data tetapan sistem. Aplikasi berniat jahat boleh merosakkan konfigurasi sistem anda."</string>
<string name="permlab_writeSecureSettings" msgid="204676251876718288">"ubah suai tetapan sistem selamat"</string>
- <!-- no translation found for permdesc_writeSecureSettings (5497873143539034724) -->
- <skip />
+ <string name="permdesc_writeSecureSettings" msgid="5497873143539034724">"Membenarkan aplikasi mengubah suai data tetapan selamat sistem. Bukan untuk kegunaan aplikasi biasa."</string>
<string name="permlab_writeGservices" msgid="2149426664226152185">"mengubah suai peta perkhidmatan Google"</string>
<string name="permdesc_writeGservices" msgid="6602362746516676175">"Membolehkan aplikasi untuk mengubah suai peta perkhidmatan Google. Bukan untuk digunakan oleh aplikasi biasa."</string>
<string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"mulakan secara automatik semasa but"</string>
- <!-- outdated translation 698336728415008796 --> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Membenarkan aplikasi memulakan dirinya sendiri sebaik sahaja sistem selesai but. Tindakan ini boleh menjadikan telefon lebih lambat untuk dimulakan dan membenarkan aplikasi itu memperlahankan keseluruhan telefon dengan sentiasa berjalan."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Membenarkan aplikasi memulakan dirinya sendiri selepas selesai pengebutan sistem. Hal ini boleh menyebabkan tablet mengambil masa lebih lama untuk dimulakan dan membenarkan aplikasi supaya sentiasa berjalan untuk memperlahankan keseluruhan tablet."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Membenarkan aplikasi memulakan dirinya sendiri sebaik sahaja sistem selesai but. Tindakan ini boleh menjadikan telefon lebih lambat untuk dimulakan dan membenarkan aplikasi itu memperlahankan keseluruhan telefon dengan sentiasa berjalan."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"hantar siaran lekit"</string>
- <!-- outdated translation 1920045289234052219 --> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Membolehkan aplikasi menghantar siaran lekit, yang tinggal selepas siaran tamat. Aplikasi berniat jahat boleh menjadikan telefon itu perlahan atau tidak stabil dengan membuatkannya menggunakan memori yang terlalu besar."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Membenarkan aplikasi menghantar siaran lekit, yang tinggal selepas siaran tamat. Aplikasi berniat jahat boleh menjadikan tablet itu perlahan atau tidak stabil dengan membuatkannya menggunakan memori yang terlalu besar."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Membolehkan aplikasi menghantar siaran lekit, yang tinggal selepas siaran tamat. Aplikasi berniat jahat boleh menjadikan telefon itu perlahan atau tidak stabil dengan membuatkannya menggunakan memori yang terlalu besar."</string>
<string name="permlab_readContacts" msgid="6219652189510218240">"baca data kenalan"</string>
- <!-- outdated translation 3371591512896545975 --> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Membenarkan aplikasi untuk membaca semua data (alamat) kenalan yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar data anda kepada orang lain."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Membenarkan aplikasi membaca semua data (alamat) kenalan yang disimpan pada tablet anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar data anda kepada orang lain."</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Membenarkan aplikasi untuk membaca semua data (alamat) kenalan yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar data anda kepada orang lain."</string>
<string name="permlab_writeContacts" msgid="644616215860933284">"tulis data kenalan"</string>
- <!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Membenarkan aplikasi mengubah suai data (alamat) kenalan yang disimpan pada telefon anda. Aplikasi yang berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data kenalan anda."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Membenarkan aplikasi mengubah suai data (alamat) kenalan yang disimpan pada tablet anda. Aplikasi yang berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data kenalan anda."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Membenarkan aplikasi mengubah suai data (alamat) kenalan yang disimpan pada telefon anda. Aplikasi yang berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data kenalan anda."</string>
- <!-- outdated translation 3728905909383989370 --> <string name="permlab_readCalendar" msgid="6898987798303840534">"baca data kalendar"</string>
- <!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Membenarkan aplikasi membaca semua acara kalendar yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar acara kalendar anda kepada orang lain."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
+ <string name="permlab_readCalendar" msgid="6898987798303840534">"baca acara kalendar"</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Membenarkan aplikasi membaca semua acara kalendar yang disimpan pada tablet anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar acara kalendar anda kepada orang lain."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Membenarkan aplikasi membaca semua acara kalendar yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk menghantar acara kalendar anda kepada orang lain."</string>
- <!-- outdated translation 377926474603567214 --> <string name="permlab_writeCalendar" msgid="3894879352594904361">"tulis data kalendar"</string>
- <!-- outdated translation 8674240662630003173 --> <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Membenarkan aplikasi mengubah suai acara kalendar yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data kalendar anda."</string>
+ <string name="permlab_writeCalendar" msgid="3894879352594904361">"tambah atau ubah suai acara kalendar dan hantar e-mel kepada tetamu"</string>
+ <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Membenarkan aplikasi untuk menambah atau menukar acara pada kalendar anda, yang mungkin menghantar e-mel kepada tetamu. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai acara kalendar anda atau menghantar e-mel kepada tetamu."</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"gunakan sumber lokasi olok-olok untuk pengujian"</string>
<string name="permdesc_accessMockLocation" msgid="7648286063459727252">"Membuat sumber lokasi olok-olok untuk pengujian. Aplikasi berniat jahat boleh menggunakannya untuk menolak lokasi dan/atau status yang dikembalikan oleh sumber lokasi sebenar seperti pembekal GPS atau Rangkaian."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"akses perintah tambahan pembekal lokasi"</string>
@@ -363,78 +348,60 @@
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"kebenaran untuk memasang pembekal lokasi"</string>
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Wujudkan sumber lokasi olokan untuk ujian. Aplikasi berniat jahat boleh menggunakannya untuk mengatasi lokasi dan/atau status yang dikembalikan oleh sumber lokasi sebenar seperti GPS atau pembekal Rangkaian atau memantau dan melaporkan lokasi anda kepada sumber luaran."</string>
<string name="permlab_accessFineLocation" msgid="8116127007541369477">"perhalusi lokasi (GPS)"</string>
- <!-- outdated translation 7411213317434337331 --> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Mengakses sumber lokasi halus seperti Sistem Kedudukan Sejagat pada telefon, sekiranya ada. Aplikasi berniat jahat boleh menggunakannya untuk menentukan lokasi anda dan boleh menggunakan kuasa bateri tambahan."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Mengakses sumber lokasi diperhalus seperti Sistem Kedudukan Sejagat pada tablet, sekiranya ada. Aplikasi berniat jahat boleh menggunakannya untuk menentukan lokasi anda dan boleh menggunakan kuasa bateri tambahan."</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Mengakses sumber lokasi halus seperti Sistem Kedudukan Sejagat pada telefon, sekiranya ada. Aplikasi berniat jahat boleh menggunakannya untuk menentukan lokasi anda dan boleh menggunakan kuasa bateri tambahan."</string>
<string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"lokasi kasar (berasaskan rangkaian)"</string>
- <!-- outdated translation 8235655958070862293 --> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Mengakses sumber lokasi kasar seperti pangkalan data rangkaian selular untuk menentukan lokasi anggaran telefon, jika tersedia. Aplikasi berniat jahat boleh menggunakannya untuk menentukan di mana anda berada."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Mengakses sumber lokasi kasar seperti pangkalan data rangkaian selular untuk menentukan lokasi anggaran tablet, sekiranya ada. Aplikasi berniat jahat boleh menggunakannya untuk menentukan anggaran tempat anda berada."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Mengakses sumber lokasi kasar seperti pangkalan data rangkaian selular untuk menentukan lokasi anggaran telefon, jika tersedia. Aplikasi berniat jahat boleh menggunakannya untuk menentukan di mana anda berada."</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"akses SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Membenarkan aplikasi menggunakan ciri peringkat rendah SurfaceFlinger."</string>
<string name="permlab_readFrameBuffer" msgid="6690504248178498136">"baca penimbal bingkai"</string>
- <!-- no translation found for permdesc_readFrameBuffer (7530020370469942528) -->
- <skip />
+ <string name="permdesc_readFrameBuffer" msgid="7530020370469942528">"Membenarkan aplikasi membaca kandungan penimbal bingkai."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"tukar tetapan audio anda"</string>
<string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Membenarkan aplikasi mengubah suai tetapan audio global seperti kelantangan dan penghalaan."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"rakam audio"</string>
<string name="permdesc_recordAudio" msgid="6493228261176552356">"Membenarkan aplikasi mengakses laluan rakaman audio"</string>
- <!-- outdated translation 8059288807274039014 --> <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar"</string>
- <!-- outdated translation 9013476258810982546 --> <string name="permdesc_camera" msgid="6004878235852154239">"Membenarkan aplikasi mengambil gambar dengan kamera. Hal ini membenarkan aplikasi mengumpul imej yang dilihat kamera pada bila-bila masa sahaja."</string>
- <!-- outdated translation 8337817093326370537 --> <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"lumpuhkan telefon secara kekal"</string>
+ <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
+ <string name="permdesc_camera" msgid="6004878235852154239">"Membenarkan aplikasi mengambil gambar dan video dengan kamera. Hal ini membenarkan aplikasi mengumpul imej yang dilihat kamera pada bila-bila masa sahaja."</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"melumpuhkan tablet secara kekal"</string>
<string name="permlab_brick" product="default" msgid="8337817093326370537">"lumpuhkan telefon secara kekal"</string>
- <!-- outdated translation 5569526552607599221 --> <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Membenarkan aplikasi melumpuhkan keseluruhan telefon secara kekal. Ini amat berbahaya."</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Membenarkan aplikasi melumpuhkan keseluruhan tablet kekal. Ini amat berbahaya."</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"Membenarkan aplikasi melumpuhkan keseluruhan telefon secara kekal. Ini amat berbahaya."</string>
- <!-- outdated translation 2898560872462638242 --> <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"paksa telefon but semula"</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"memaksa tablet but semula"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"paksa telefon but semula"</string>
- <!-- outdated translation 7914933292815491782 --> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Membenarkan aplikasi memaksa telefon untuk but semula."</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Membenarkan aplikasi memaksa tablet untuk but semula."</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Membenarkan aplikasi memaksa telefon untuk but semula."</string>
<string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"melekapkan dan menyahlekapkan sistem fail"</string>
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Membenarkan aplikasi melekapkan dan menyahlekapkan sistem fail untuk storan boleh tanggal."</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"format storan luaran"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Membenarkan aplikasi memformat storan boleh tanggal."</string>
- <!-- no translation found for permlab_asec_access (3411338632002193846) -->
- <skip />
- <!-- no translation found for permdesc_asec_access (8820326551687285439) -->
- <skip />
- <!-- no translation found for permlab_asec_create (6414757234789336327) -->
- <skip />
- <!-- no translation found for permdesc_asec_create (2621346764995731250) -->
- <skip />
- <!-- no translation found for permlab_asec_destroy (526928328301618022) -->
- <skip />
- <!-- no translation found for permdesc_asec_destroy (2746706889208066256) -->
- <skip />
- <!-- no translation found for permlab_asec_mount_unmount (2456287623689029744) -->
- <skip />
- <!-- no translation found for permdesc_asec_mount_unmount (5934375590189368200) -->
- <skip />
- <!-- no translation found for permlab_asec_rename (7496633954080472417) -->
- <skip />
- <!-- no translation found for permdesc_asec_rename (2152829985238876790) -->
- <skip />
+ <string name="permlab_asec_access" msgid="3411338632002193846">"dapatkan maklumat tentang storan dalaman"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Membenarkan aplikasi mendapatkan maklumat pada storan dalaman."</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"buat storan dalaman"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Membenarkan aplikasi membuat storan dalaman."</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"memusnahkan storan dalaman"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Membenarkan aplikasi memusnahkan storan dalaman."</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"lekap / nyahlekap storan dalaman"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Membenarkan aplikasi melekapkan / menyahlekapkan storan dalaman."</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"namakan semula storan dalaman"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Membenarkan aplikasi menamakan semula storan dalaman."</string>
<string name="permlab_vibrate" msgid="7768356019980849603">"kawal penggetar"</string>
<string name="permdesc_vibrate" msgid="2886677177257789187">"Membenarkan aplikasi mengawal penggetar."</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"mengawal lampu suluh"</string>
<string name="permdesc_flashlight" msgid="6433045942283802309">"Membenarkan aplikasi mengawal lampu suluh."</string>
- <!-- no translation found for permlab_manageUsb (1113453430645402723) -->
- <skip />
- <!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
- <skip />
- <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
- <skip />
- <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
- <skip />
+ <string name="permlab_manageUsb" msgid="1113453430645402723">"urus pilihan dan kebenaran untuk peranti USB"</string>
+ <string name="permdesc_manageUsb" msgid="6148489202092166164">"Membenarkan aplikasi untuk menguruskan pilihan dan kebenaran untuk peranti USB."</string>
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"laksanakan protokol MTP"</string>
+ <string name="permdesc_accessMtp" msgid="6532961200486791570">"Membenarkan akses kepada pemacu inti MTP untuk melaksanakan protokol USB MTP."</string>
<string name="permlab_hardware_test" msgid="4148290860400659146">"uji perkakasan"</string>
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Membenarkan aplikasi mengawal pelbagai persisian untuk tujuan pengujian perkakasan."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"panggil terus nombor telefon"</string>
<string name="permdesc_callPhone" msgid="3369867353692722456">"Membenarkan aplikasi memanggil nombor telefon tanpa campur tangan anda. Aplikasi berniat jahat boleh menyebabkan panggilan yang tidak dijangka tersenarai dalam bil telefon anda. Ambil perhatian bahawa hal ini tidak membenarkan aplikasi memanggil nombor kecemasan."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"panggil terus sebarang nombor telefon"</string>
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Membenarkan aplikasi memanggil sebarang nombor telefon, termasuk nombor kecemasan, tanpa campur tangan anda. Aplikasi berniat jahat boleh membuat panggilan yang tidak perlu serta tanpa izin ke perkhidmatan kecemasan."</string>
- <!-- no translation found for permlab_performCdmaProvisioning (4842576994144604821) -->
- <skip />
- <!-- no translation found for permlab_performCdmaProvisioning (5604848095315421425) -->
- <skip />
- <!-- no translation found for permdesc_performCdmaProvisioning (6457447676108355905) -->
- <skip />
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"mulakan terus persediaan tablet CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"memulakan persediaan telefon CDMA secara langsung"</string>
+ <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Membenarkan aplikasi memulakan peruntukan CDMA. Aplikasi berniat jahat boleh memulakan peruntukan CDMA yang tidak perlu"</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"kawal pemberitahuan kemas kini lokasi"</string>
<string name="permdesc_locationUpdates" msgid="2300018303720930256">"Membenarkan pemberitahuan kemas kini lokasi didayakan/dilumpuhkan dari radio. Bukan untuk digunakan oleh aplikasi biasa."</string>
<string name="permlab_checkinProperties" msgid="7855259461268734914">"akses sifat daftar masuk"</string>
@@ -443,20 +410,18 @@
<string name="permdesc_bindGadget" msgid="2098697834497452046">"Membenarkan aplikasi memberitahu sistem widget yang mana boleh digunakan oleh aplikasi yang mana. Dengan kebenaran ini, aplikasi boleh memberikan akses kepada data peribadi kepada aplikasi lain. Bukan untuk digunakan oleh aplikasi biasa."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"ubah suai keadaan telefon"</string>
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Membenarkan aplikasi mengawal ciri telefon peranti. Aplikasi dengan kebenaran ini boleh bertukar rangkaian, menghidupkan dan mematikan radio telefon serta perkara-perkara sepertinya tanpa sekali-kali memberitahu anda."</string>
- <!-- no translation found for permlab_readPhoneState (2326172951448691631) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneState (188877305147626781) -->
- <skip />
- <!-- outdated translation 573480187941496130 --> <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"halang telefon daripada tidur"</string>
+ <string name="permlab_readPhoneState" msgid="2326172951448691631">"baca keadaan dan identiti telefon"</string>
+ <string name="permdesc_readPhoneState" msgid="188877305147626781">"Membenarkan aplikasi mengakses ciri telefon peranti. Aplikasi dengan kebenaran ini boleh menentukan nombor telefon dan nombor siri telefon ini, sama ada panggilan aktif ataupun tidak, nombor yang disambungkan dan yang seumpamanya."</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"menghalang tablet daripada tidur"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"halang telefon daripada tidur"</string>
- <!-- outdated translation 7584036471227467099 --> <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Membenarkan aplikasi menghalang telefon daripada tidur."</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Membenarkan aplikasi menghalang tablet daripada tidur."</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Membenarkan aplikasi menghalang telefon daripada tidur."</string>
- <!-- outdated translation 4928622470980943206 --> <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"kuasakan telefon hidup atau mati"</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"menghidupkan atau mematikan kuasa tablet"</string>
<string name="permlab_devicePower" product="default" msgid="4928622470980943206">"kuasakan telefon hidup atau mati"</string>
- <!-- outdated translation 4577331933252444818 --> <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Membenarkan aplikasi menghidupkan atau mematikan telefon."</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Membenarkan aplikasi menghidupkan atau mematikan tablet."</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Membenarkan aplikasi menghidupkan atau mematikan telefon."</string>
<string name="permlab_factoryTest" msgid="3715225492696416187">"jalankan dalam mod ujian kilang"</string>
- <!-- outdated translation 8136644990319244802 --> <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Menjalankan sebagai ujian pengilang peringkat rendah, membenarkan akses penuh kepada perkakasan telefon. Hanya tersedia apabila telefon dijalankan dalam mod ujian pengilang."</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Jalankan sebagai ujian pengeluar peringkat rendah, membenarkan akses penuh kepada perkakasan tablet. Hanya tersedia apabila tablet dijalankan dalam mod ujian pengeluar."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Menjalankan sebagai ujian pengilang peringkat rendah, membenarkan akses penuh kepada perkakasan telefon. Hanya tersedia apabila telefon dijalankan dalam mod ujian pengilang."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"tetapkan kertas dinding"</string>
<string name="permdesc_setWallpaper" msgid="6417041752170585837">"Membenarkan aplikasi menetapkan kertas dinding sistem"</string>
@@ -464,34 +429,23 @@
<string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"Membenarkan aplikasi menetapkan saiz kertas dinding sistem kepada saiz pembayang."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"menetapkan semula sistem kepada lalai kilang"</string>
<string name="permdesc_masterClear" msgid="5033465107545174514">"Membenarkan aplikasi menetapkan semula sistem sepenuhnya kepada tetapan kilang, memadam semua data, konfigurasi dan aplikasi yang dipasang."</string>
- <!-- no translation found for permlab_setTime (2021614829591775646) -->
- <skip />
- <!-- no translation found for permdesc_setTime (209693136361006073) -->
- <skip />
- <!-- no translation found for permdesc_setTime (667294309287080045) -->
- <skip />
+ <string name="permlab_setTime" msgid="2021614829591775646">"tetapkan masa"</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Membenarkan aplikasi menukar waktu jam tablet."</string>
+ <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Membenarkan aplikasi menukar waktu jam telefon."</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"tetapkan zon waktu"</string>
- <!-- outdated translation 1902540227418179364 --> <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Membenarkan aplikasi menukar zon waktu telefon."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Membenarkan aplikasi menukar zon waktu tablet."</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Membenarkan aplikasi menukar zon waktu telefon."</string>
- <!-- no translation found for permlab_accountManagerService (4829262349691386986) -->
- <skip />
- <!-- no translation found for permdesc_accountManagerService (6056903274106394752) -->
- <skip />
+ <string name="permlab_accountManagerService" msgid="4829262349691386986">"bertindak sebagai PerkhidmatanPengurusAkaun"</string>
+ <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Membenarkan aplikasi membuat panggilan ke PengesahAkaun"</string>
<string name="permlab_getAccounts" msgid="4549918644233460103">"menemui akaun yang diketahui"</string>
- <!-- outdated translation 6839262446413155394 --> <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Membenarkan aplikasi mendapatkan senarai akaun yang diketahui telefon."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Membenarkan aplikasi mendapatkan senarai akaun yang diketahui tablet."</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Membenarkan aplikasi mendapatkan senarai akaun yang diketahui telefon."</string>
- <!-- no translation found for permlab_authenticateAccounts (3940505577982882450) -->
- <skip />
- <!-- no translation found for permdesc_authenticateAccounts (4006839406474208874) -->
- <skip />
- <!-- no translation found for permlab_manageAccounts (4440380488312204365) -->
- <skip />
- <!-- no translation found for permdesc_manageAccounts (8804114016661104517) -->
- <skip />
- <!-- no translation found for permlab_useCredentials (6401886092818819856) -->
- <skip />
- <!-- no translation found for permdesc_useCredentials (7416570544619546974) -->
- <skip />
+ <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"sebagai pengesah akaun"</string>
+ <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Membenarkan aplikasi menggunakan kebolehan pengesah akaun Pengurus Akaun, termasuk membuat akaun dan mendapatkan serta menetapkan kata laluannya."</string>
+ <string name="permlab_manageAccounts" msgid="4440380488312204365">"urus senarai akaun"</string>
+ <string name="permdesc_manageAccounts" msgid="8804114016661104517">"Membenarkan aplikasi melaksanakan pengendalian seperti menambah dan mengalih keluar akaun dan memadamkan kata laluannya."</string>
+ <string name="permlab_useCredentials" msgid="6401886092818819856">"menggunakan bukti kelayakan pengesahan akaun"</string>
+ <string name="permdesc_useCredentials" msgid="7416570544619546974">"Membenarkan aplikasi meminta token pengesahan."</string>
<string name="permlab_accessNetworkState" msgid="6865575199464405769">"lihat keadaan rangkaian"</string>
<string name="permdesc_accessNetworkState" msgid="558721128707712766">"Membenarkan aplikasi melihat keadaan semua rangkaian."</string>
<string name="permlab_createNetworkSockets" msgid="9121633680349549585">"akses penuh Internet"</string>
@@ -499,11 +453,9 @@
<string name="permlab_writeApnSettings" msgid="7823599210086622545">"tulis tetapan Nama Titik Capaian"</string>
<string name="permdesc_writeApnSettings" msgid="7443433457842966680">"Membenarkan aplikasi mengubah suai tetapan APN, seperti Proksi dan Port mana-mana APN."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"tukar kesambungan rangkaian"</string>
- <!-- outdated translation 6278115726355634395 --> <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Membenarkan aplikasi menukar kesambungan rangkaian keadaan"</string>
- <!-- no translation found for permlab_changeTetherState (2702121155761140799) -->
- <skip />
- <!-- no translation found for permdesc_changeTetherState (8905815579146349568) -->
- <skip />
+ <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"Membenarkan aplikasi menukar keadaan kesambungan rangkaian."</string>
+ <string name="permlab_changeTetherState" msgid="2702121155761140799">"Tukar kesambungan bertambat"</string>
+ <string name="permdesc_changeTetherState" msgid="8905815579146349568">"Membenarkan aplikasi menukar keadaan kesambungan rangkaian tambatan."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"tukar tetapan penggunaan data latar belakang"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"Membenarkan aplikasi menukar tetapan penggunaan data latar belakang."</string>
<string name="permlab_accessWifiState" msgid="8100926650211034400">"lihat keadaan Wi-Fi"</string>
@@ -513,18 +465,16 @@
<string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"benarkan penerimaan Wi-Fi Multisiar"</string>
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Membenarkan aplikasi menerima bingkisan yang tidak ditujukan secara langsung ke peranti anda. Hal ini boleh menjadi berguna apabila menemui perkhidmatan yang ditawarkan di kawasan berdekatan. Ia menggunakan lebih banyak kuasa daripada mod bukan multisiar."</string>
<string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"pentadbiran bluetooth"</string>
- <!-- outdated translation 7256289774667054555 --> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Membenarkan aplikasi mengkonfigurasikan telefon Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Membenarkan aplikasi mengkonfigurasikan tablet Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Membenarkan aplikasi mengkonfigurasikan telefon Bluetooth setempat dan menemui serta berpasangan dengan peranti jauh."</string>
<string name="permlab_bluetooth" msgid="8361038707857018732">"buat sambungan Bluetooth"</string>
- <!-- outdated translation 762515380679392945 --> <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Membenarkan aplikasi melihat konfigurasi telefon Bluetooth setempat dan membuat dan menerima sambungan dengan peranti yang dipasangkan."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Membenarkan aplikasi melihat konfigurasi tablet Bluetooth setempat dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Membenarkan aplikasi melihat konfigurasi telefon Bluetooth setempat dan membuat dan menerima sambungan dengan peranti yang dipasangkan."</string>
- <!-- no translation found for permlab_nfc (4423351274757876953) -->
- <skip />
- <!-- no translation found for permdesc_nfc (9171401851954407226) -->
- <skip />
+ <string name="permlab_nfc" msgid="4423351274757876953">"mengawal Komunikasi Medan Dekat"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Membenarkan aplikasi berkomunikasi dengan teg, kad dan pembaca Komunikasi Medan Dekat (NFC)."</string>
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"lumpuhkan kunci kekunci"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Membenarkan aplikasi melumpuhkan kunci kekunci anda dan sebarang keselamatan kata laluan yang berkaitan. Contoh yang berkaitan adalah telefon melumpuhkan kunci kekunci apabila menerima panggilan telefon masuk kemudian mendayakan semula kunci kekunci apabila panggilan selesai."</string>
@@ -542,57 +492,45 @@
<string name="permdesc_readDictionary" msgid="1082972603576360690">"Membenarkan aplikasi membaca sebarang kata-kata peribadi, nama dan frasa yang mungkin telah disimpan oleh pengguna dalam kamus pengguna."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"tulis ke kamus yang ditakrifkan pengguna"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"Membenarkan aplikasi menulis perkataan baru ke dalam kamus pengguna."</string>
- <!-- outdated translation 8079403759001777291 --> <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"ubah suai/padamkan kandungan kad SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"ubah suai/padam kdgn storn USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ubah suai/padamkan kandungan kad SD"</string>
- <!-- outdated translation 6643963204976471878 --> <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Membenarkan aplikasi menulis ke kad SD."</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Bnrkn apl menulis ke strn USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Membenarkan aplikasi menulis ke kad SD."</string>
- <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ubh suai/pdm kdg strn mdia dlm"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Membenarkan aplikasi mengubah suai kandungan storan media dalaman."</string>
+ <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem fail cache"</string>
+ <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Membenarkan aplikasi membaca dan menulis cache sistem fail."</string>
+ <string name="permlab_use_sip" msgid="5986952362795870502">"membuat/menerima panggilan Internet"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Membenarkan aplikasi menggunakan perkhidmatan SIP untuk membuat/menerima panggilan Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
<skip />
- <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
<skip />
- <!-- no translation found for permlab_cache_filesystem (5656487264819669824) -->
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
<skip />
- <!-- no translation found for permdesc_cache_filesystem (1624734528435659906) -->
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
<skip />
- <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+ <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
+ <string name="policydesc_limitPassword" msgid="9083400080861728056">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin"</string>
+ <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Memantau bilangan kata laluan salah yang dimasukkan semasa membuka kunci skrin dan mengunci tablet atau memadamkan semua data tablet jika terlalu banyak kata laluan salah dimasukkan"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Memantau bilangan kata laluan salah yang dimasukkan semasa membuka kunci skrin, dan mengunci telefon atau memadamkan semua data telefon jika terlalu banyak kata laluan salah dimasukkan"</string>
+ <string name="policylab_resetPassword" msgid="2620077191242688955">"Tukar kata laluan buka kunci skrin"</string>
+ <string name="policydesc_resetPassword" msgid="5391240616981297361">"Tukar kata laluan buka kunci skrin"</string>
+ <string name="policylab_forceLock" msgid="2274085384704248431">"Kunci skrin"</string>
+ <string name="policydesc_forceLock" msgid="5696964126226028442">"Mengawal bagaimana dan bila skrin dikunci"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"Padamkan semua data"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Memadamkan data tablet tanpa memberikan amaran, dengan melakukan tetapan semula data kilang"</string>
+ <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Memadamkan data telefon tanpa memberikan amaran, dengan melakukan tetapan semula data kilang"</string>
+ <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Tetapkan proksi global peranti"</string>
+ <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Menetapkan proksi global peranti untuk digunakan sementara dasar didayakan. Hanya pentadbir peranti pertama boleh menetapkan proksi global dengan berkesan."</string>
+ <string name="policylab_expirePassword" msgid="885279151847254056">"Ttpkn tmt tmph k/lln kci skrin"</string>
+ <string name="policydesc_expirePassword" msgid="4844430354224822074">"Mengawal kekerapan penukaran kata laluan kunci skrin"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Tetapkan penyulitan storan"</string>
+ <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Memerlukan data aplikasi yang disimpan itu disulitkan"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
- <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
- <skip />
- <!-- no translation found for policylab_limitPassword (4497420728857585791) -->
- <skip />
- <!-- no translation found for policydesc_limitPassword (9083400080861728056) -->
- <skip />
- <!-- no translation found for policylab_watchLogin (914130646942199503) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin (933601759466308092) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin (7227578260165172673) -->
- <skip />
- <!-- no translation found for policylab_resetPassword (2620077191242688955) -->
- <skip />
- <!-- no translation found for policydesc_resetPassword (5391240616981297361) -->
- <skip />
- <!-- no translation found for policylab_forceLock (2274085384704248431) -->
- <skip />
- <!-- no translation found for policydesc_forceLock (5696964126226028442) -->
- <skip />
- <!-- no translation found for policylab_wipeData (3910545446758639713) -->
- <skip />
- <!-- no translation found for policydesc_wipeData (314455232799486222) -->
- <skip />
- <!-- no translation found for policydesc_wipeData (7669895333814222586) -->
- <skip />
- <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
- <skip />
- <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
- <skip />
- <!-- no translation found for policylab_expirePassword (885279151847254056) -->
- <skip />
- <!-- no translation found for policydesc_expirePassword (4844430354224822074) -->
- <skip />
- <!-- no translation found for policylab_encryptedStorage (8901326199909132915) -->
- <skip />
- <!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
<skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Laman Utama"</item>
@@ -637,153 +575,86 @@
<item msgid="2506857312718630823">"ICQ"</item>
<item msgid="1648797903785279353">"Jabber"</item>
</string-array>
- <!-- no translation found for phoneTypeCustom (1644738059053355820) -->
- <skip />
- <!-- no translation found for phoneTypeHome (2570923463033985887) -->
- <skip />
- <!-- no translation found for phoneTypeMobile (6501463557754751037) -->
- <skip />
- <!-- no translation found for phoneTypeWork (8863939667059911633) -->
- <skip />
- <!-- no translation found for phoneTypeFaxWork (3517792160008890912) -->
- <skip />
- <!-- no translation found for phoneTypeFaxHome (2067265972322971467) -->
- <skip />
- <!-- no translation found for phoneTypePager (7582359955394921732) -->
- <skip />
- <!-- no translation found for phoneTypeOther (1544425847868765990) -->
- <skip />
- <!-- no translation found for phoneTypeCallback (2712175203065678206) -->
- <skip />
- <!-- no translation found for phoneTypeCar (8738360689616716982) -->
- <skip />
- <!-- no translation found for phoneTypeCompanyMain (540434356461478916) -->
- <skip />
- <!-- no translation found for phoneTypeIsdn (8022453193171370337) -->
- <skip />
- <!-- no translation found for phoneTypeMain (6766137010628326916) -->
- <skip />
- <!-- no translation found for phoneTypeOtherFax (8587657145072446565) -->
- <skip />
- <!-- no translation found for phoneTypeRadio (4093738079908667513) -->
- <skip />
- <!-- no translation found for phoneTypeTelex (3367879952476250512) -->
- <skip />
- <!-- no translation found for phoneTypeTtyTdd (8606514378585000044) -->
- <skip />
- <!-- no translation found for phoneTypeWorkMobile (1311426989184065709) -->
- <skip />
- <!-- no translation found for phoneTypeWorkPager (649938731231157056) -->
- <skip />
- <!-- no translation found for phoneTypeAssistant (5596772636128562884) -->
- <skip />
- <!-- no translation found for phoneTypeMms (7254492275502768992) -->
- <skip />
- <!-- no translation found for eventTypeCustom (7837586198458073404) -->
- <skip />
- <!-- no translation found for eventTypeBirthday (2813379844211390740) -->
- <skip />
- <!-- no translation found for eventTypeAnniversary (3876779744518284000) -->
- <skip />
- <!-- no translation found for eventTypeOther (7388178939010143077) -->
- <skip />
- <!-- no translation found for emailTypeCustom (8525960257804213846) -->
- <skip />
- <!-- no translation found for emailTypeHome (449227236140433919) -->
- <skip />
- <!-- no translation found for emailTypeWork (3548058059601149973) -->
- <skip />
- <!-- no translation found for emailTypeOther (2923008695272639549) -->
- <skip />
- <!-- no translation found for emailTypeMobile (119919005321166205) -->
- <skip />
- <!-- no translation found for postalTypeCustom (8903206903060479902) -->
- <skip />
- <!-- no translation found for postalTypeHome (8165756977184483097) -->
- <skip />
- <!-- no translation found for postalTypeWork (5268172772387694495) -->
- <skip />
- <!-- no translation found for postalTypeOther (2726111966623584341) -->
- <skip />
- <!-- no translation found for imTypeCustom (2074028755527826046) -->
- <skip />
- <!-- no translation found for imTypeHome (6241181032954263892) -->
- <skip />
- <!-- no translation found for imTypeWork (1371489290242433090) -->
- <skip />
- <!-- no translation found for imTypeOther (5377007495735915478) -->
- <skip />
- <!-- no translation found for imProtocolCustom (6919453836618749992) -->
- <skip />
- <!-- no translation found for imProtocolAim (7050360612368383417) -->
- <skip />
- <!-- no translation found for imProtocolMsn (144556545420769442) -->
- <skip />
- <!-- no translation found for imProtocolYahoo (8271439408469021273) -->
- <skip />
- <!-- no translation found for imProtocolSkype (9019296744622832951) -->
- <skip />
- <!-- no translation found for imProtocolQq (8887484379494111884) -->
- <skip />
- <!-- no translation found for imProtocolGoogleTalk (3808393979157698766) -->
- <skip />
- <!-- no translation found for imProtocolIcq (1574870433606517315) -->
- <skip />
- <!-- no translation found for imProtocolJabber (2279917630875771722) -->
- <skip />
- <!-- no translation found for imProtocolNetMeeting (8287625655986827971) -->
- <skip />
- <!-- no translation found for orgTypeWork (29268870505363872) -->
- <skip />
- <!-- no translation found for orgTypeOther (3951781131570124082) -->
- <skip />
- <!-- no translation found for orgTypeCustom (225523415372088322) -->
- <skip />
- <!-- no translation found for relationTypeCustom (3542403679827297300) -->
- <skip />
- <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
- <skip />
- <!-- no translation found for relationTypeBrother (8757913506784067713) -->
- <skip />
- <!-- no translation found for relationTypeChild (1890746277276881626) -->
- <skip />
- <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
- <skip />
- <!-- no translation found for relationTypeFather (5228034687082050725) -->
- <skip />
- <!-- no translation found for relationTypeFriend (7313106762483391262) -->
- <skip />
- <!-- no translation found for relationTypeManager (6365677861610137895) -->
- <skip />
- <!-- no translation found for relationTypeMother (4578571352962758304) -->
- <skip />
- <!-- no translation found for relationTypeParent (4755635567562925226) -->
- <skip />
- <!-- no translation found for relationTypePartner (7266490285120262781) -->
- <skip />
- <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
- <skip />
- <!-- no translation found for relationTypeRelative (1799819930085610271) -->
- <skip />
- <!-- no translation found for relationTypeSister (1735983554479076481) -->
- <skip />
- <!-- no translation found for relationTypeSpouse (394136939428698117) -->
- <skip />
- <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
- <skip />
- <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
- <skip />
- <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
- <skip />
- <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
- <skip />
+ <string name="phoneTypeCustom" msgid="1644738059053355820">"Peribadi"</string>
+ <string name="phoneTypeHome" msgid="2570923463033985887">"Laman Utama"</string>
+ <string name="phoneTypeMobile" msgid="6501463557754751037">"Mudah Alih"</string>
+ <string name="phoneTypeWork" msgid="8863939667059911633">"Kerja"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"Faks Kerja"</string>
+ <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Faks Rumah"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"Alat Kelui"</string>
+ <string name="phoneTypeOther" msgid="1544425847868765990">"Lain-lain"</string>
+ <string name="phoneTypeCallback" msgid="2712175203065678206">"Panggil balik"</string>
+ <string name="phoneTypeCar" msgid="8738360689616716982">"Kereta"</string>
+ <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Nombor Utama Syarikat"</string>
+ <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
+ <string name="phoneTypeMain" msgid="6766137010628326916">"Utama"</string>
+ <string name="phoneTypeOtherFax" msgid="8587657145072446565">"Faks Lain"</string>
+ <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
+ <string name="phoneTypeTelex" msgid="3367879952476250512">"Teleks"</string>
+ <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
+ <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Telefon Mudah Alih Kerja"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"Alat Kelui Kerja"</string>
+ <string name="phoneTypeAssistant" msgid="5596772636128562884">"Pembantu"</string>
+ <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Peribadi"</string>
+ <string name="eventTypeBirthday" msgid="2813379844211390740">"Hari Lahir"</string>
+ <string name="eventTypeAnniversary" msgid="3876779744518284000">"Ulang tahun"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"Lain-lain"</string>
+ <string name="emailTypeCustom" msgid="8525960257804213846">"Peribadi"</string>
+ <string name="emailTypeHome" msgid="449227236140433919">"Rumah"</string>
+ <string name="emailTypeWork" msgid="3548058059601149973">"Kerja"</string>
+ <string name="emailTypeOther" msgid="2923008695272639549">"Lain-lain"</string>
+ <string name="emailTypeMobile" msgid="119919005321166205">"Mudah Alih"</string>
+ <string name="postalTypeCustom" msgid="8903206903060479902">"Peribadi"</string>
+ <string name="postalTypeHome" msgid="8165756977184483097">"Laman Utama"</string>
+ <string name="postalTypeWork" msgid="5268172772387694495">"Kerja"</string>
+ <string name="postalTypeOther" msgid="2726111966623584341">"Lain-lain"</string>
+ <string name="imTypeCustom" msgid="2074028755527826046">"Peribadi"</string>
+ <string name="imTypeHome" msgid="6241181032954263892">"Laman Utama"</string>
+ <string name="imTypeWork" msgid="1371489290242433090">"Kerja"</string>
+ <string name="imTypeOther" msgid="5377007495735915478">"Lain-lain"</string>
+ <string name="imProtocolCustom" msgid="6919453836618749992">"Peribadi"</string>
+ <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
+ <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
+ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
+ <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string>
+ <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string>
+ <string name="imProtocolGoogleTalk" msgid="3808393979157698766">"Bual Google"</string>
+ <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string>
+ <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string>
+ <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
+ <string name="orgTypeWork" msgid="29268870505363872">"Kerja"</string>
+ <string name="orgTypeOther" msgid="3951781131570124082">"Lain-lain"</string>
+ <string name="orgTypeCustom" msgid="225523415372088322">"Peribadi"</string>
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Peribadi"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"Pembantu"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Abang/Adik"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Anak"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Rakan Kongsi Domestik"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Bapa"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Rakan"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Pengurus"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Ibu"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"Ibu bapa"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Rakan Kongsi"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Dirujuk oleh"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Saudara"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Kakak/Adik"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Pasangan"</string>
+ <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Peribadi"</string>
+ <string name="sipAddressTypeHome" msgid="6093598181069359295">"Laman Utama"</string>
+ <string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerja"</string>
+ <string name="sipAddressTypeOther" msgid="4408436162950119849">"Lain-lain"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Masukkan kod PIN"</string>
- <!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
<skip />
- <!-- no translation found for keyguard_password_enter_password_code (9138158344813213754) -->
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
<skip />
- <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
<skip />
+ <string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Sentuh untuk memasukkan kata laluan"</font></string>
+ <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Masukkan kata laluan untuk membuka kunci"</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Masukkan PIN untuk membuka kunci"</string>
<string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Kod PIN salah!"</string>
<string name="keyguard_label_text" msgid="861796461028298424">"Untuk membuka kunci, tekan Menu, kemudian 0."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Nombor kecemasan"</string>
@@ -793,64 +664,50 @@
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Tekan Menu untuk membuka kunci."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Lukiskan corak untuk membuka kunci"</string>
<string name="lockscreen_emergency_call" msgid="5347633784401285225">"Panggilan kecemasan"</string>
- <!-- no translation found for lockscreen_return_to_call (5244259785500040021) -->
- <skip />
+ <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Kembali ke panggilan"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Betul!"</string>
<string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Maaf, cuba lagi"</string>
- <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
- <skip />
+ <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Maaf, cuba lagi"</string>
<string name="lockscreen_plugged_in" msgid="613343852842944435">"Mengecas (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
- <!-- no translation found for lockscreen_charged (4938930459620989972) -->
- <skip />
- <!-- no translation found for lockscreen_battery_short (3617549178603354656) -->
- <skip />
+ <string name="lockscreen_charged" msgid="4938930459620989972">"Sudah dicas."</string>
+ <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Sambungkan pengecas anda."</string>
<string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tiada kad SIM."</string>
- <!-- outdated translation 2186920585695169078 --> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Kad SIM tiada dalam telefon."</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tiada kad SIM dalam tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Kad SIM tiada dalam telefon."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sila masukkan kad SIM."</string>
- <!-- no translation found for emergency_calls_only (6733978304386365407) -->
- <!-- no translation found for emergency_calls_only (2485604591272668370) -->
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
<skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
+ <string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan kecemasan sahaja"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rangkaian dikunci"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kad SIM dikunci dengan PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"Sila lihat Panduan Pengguna atau hubungi Penjagaan Pelanggan."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kad SIM dikunci."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Membuka kunci kad SIM..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Anda telah melukis corak buka kunci anda dengan salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Sila cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
- <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
- <skip />
- <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
- <skip />
- <!-- no translation found for lockscreen_failed_attempts_almost_glogin (8687762517114904651) -->
- <skip />
+ <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Anda telah memasukkan kata laluan anda secara salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Sila cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Anda telah memasukkan PIN anda secara salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Sila cuba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> saat."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Anda telah melukis corak buka kunci dengan salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci tablet anda menggunakan log masuk Google anda."\n\n" Sila cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Anda telah melukis corak buka kunci dengan salah sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda."\n\n" Sila cuba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> saat."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Cuba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> saat."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Lupa corak?"</string>
- <!-- no translation found for lockscreen_glogin_forgot_pattern (2588521501166032747) -->
- <skip />
+ <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Buka kunci akaun"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="2446246026221678244">"Terlalu banyak percubaan melukis corak!"</string>
<string name="lockscreen_glogin_instructions" msgid="1816635201812207709">"Untuk membuka kunci, log masuk dengan akaun Google anda"</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Nama Pengguna (E-mel)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Kata laluan"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Log masuk"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Nama pengguna atau kata laluan tidak sah."</string>
- <!-- no translation found for lockscreen_glogin_account_recovery_hint (8253152905532900548) -->
- <skip />
- <!-- no translation found for lockscreen_glogin_checking_password (6758890536332363322) -->
- <skip />
- <!-- no translation found for lockscreen_unlock_label (737440483220667054) -->
- <skip />
- <!-- no translation found for lockscreen_sound_on_label (9068877576513425970) -->
- <skip />
- <!-- no translation found for lockscreen_sound_off_label (996822825154319026) -->
- <skip />
- <!-- no translation found for password_keyboard_label_symbol_key (992280756256536042) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alpha_key (8001096175167485649) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alt_key (1284820942620288678) -->
- <skip />
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="8253152905532900548">"Lupa nama pengguna atau kata laluan anda?"\n"Lawati "<b>"google.com/accounts/recovery"</b></string>
+ <string name="lockscreen_glogin_checking_password" msgid="6758890536332363322">"Menyemak..."</string>
+ <string name="lockscreen_unlock_label" msgid="737440483220667054">"Buka kunci"</string>
+ <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Bunyi dihidupkan"</string>
+ <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Bunyi dimatikan"</string>
+ <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
+ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
+ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"Ujian kilang gagal"</string>
@@ -861,33 +718,22 @@
<string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
<string name="js_dialog_before_unload" msgid="1901675448179653089">"Navigasi keluar dari halaman ini?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Pilih OK untuk meneruskan atau Batal untuk terus berada di halaman semasa."</string>
<string name="save_password_label" msgid="6860261758665825069">"Sahkan"</string>
- <!-- no translation found for double_tap_toast (1068216937244567247) -->
- <skip />
- <!-- no translation found for autofill_this_form (1272247532604569872) -->
- <skip />
- <!-- no translation found for setup_autofill (8154593408885654044) -->
- <skip />
- <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
- <skip />
- <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
- <skip />
- <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
- <skip />
- <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
- <skip />
+ <string name="double_tap_toast" msgid="1068216937244567247">"Petua: ketik dua kali untuk mengezum masuk dan keluar."</string>
+ <string name="autofill_this_form" msgid="1272247532604569872">"AutoIsi"</string>
+ <string name="setup_autofill" msgid="8154593408885654044">"Sediakan AutoIsi"</string>
+ <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca sejarah dan penanda halaman Penyemak imbas"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Membenarkan aplikasi membaca semua URL yang telah dilawati oleh Penyemak Imbas dan semua penanda halaman Penyemak Imbas."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tulis sejarah dan penanda halaman Penyemak Imbas"</string>
- <!-- outdated translation 945571990357114950 --> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Membenarkan aplikasi mengubah suai sejarah atau penanda halaman Penyemak Imbas yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah data Penyemak Imbas anda."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Membenarkan aplikasi mengubah suai sejarah atau penanda halaman Penyemak Imbas yang disimpan pada tablet anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah suai data Penyemak Imbas anda."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Membenarkan aplikasi mengubah suai sejarah atau penanda halaman Penyemak Imbas yang disimpan pada telefon anda. Aplikasi berniat jahat boleh menggunakannya untuk memadamkan atau mengubah data Penyemak Imbas anda."</string>
- <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
- <skip />
- <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
- <skip />
- <!-- no translation found for permlab_writeGeolocationPermissions (4715212655598275532) -->
- <skip />
- <!-- no translation found for permdesc_writeGeolocationPermissions (4011908282980861679) -->
- <skip />
+ <string name="permlab_setAlarm" msgid="5924401328803615165">"menetapkan penggera dalam jam penggera"</string>
+ <string name="permdesc_setAlarm" msgid="5966966598149875082">"Membenarkan aplikasi menetapkan penggera dalam aplikasi jam penggera yang dipasang. Sesetengah aplikasi jam penggera mungkin tidak melaksanakan ciri ini."</string>
+ <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ubah suai kebenaran geolokasi Penyemak Imbas"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Membenarkan aplikasi mengubah suai kebenaran geolokasi Penyemak Imbas. Aplikasi berniat jahat boleh menggunakannya untuk membenarkan penghantaran maklumat lokasi ke sembarangan tapak web."</string>
<string name="save_password_message" msgid="767344687139195790">"Adakah anda mahu penyemak imbas mengingati kata laluan ini?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Bukan sekarang"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
@@ -914,11 +760,11 @@
<item quantity="one" msgid="9150797944610821849">"1 jam yang lalu"</item>
<item quantity="other" msgid="2467273239587587569">"<xliff:g id="COUNT">%d</xliff:g> jam yang lalu"</item>
</plurals>
- <!-- no translation found for last_num_days:other (3069992808164318268) -->
- <!-- no translation found for last_month (3959346739979055432) -->
- <skip />
- <!-- no translation found for older (5211975022815554840) -->
- <skip />
+ <plurals name="last_num_days">
+ <item quantity="other" msgid="3069992808164318268">"<xliff:g id="COUNT">%d</xliff:g> hari terakhir"</item>
+ </plurals>
+ <string name="last_month" msgid="3959346739979055432">"Bulan lepas"</string>
+ <string name="older" msgid="5211975022815554840">"Lebih lama"</string>
<plurals name="num_days_ago">
<item quantity="one" msgid="861358534398115820">"semalam"</item>
<item quantity="other" msgid="2479586466153314633">"<xliff:g id="COUNT">%d</xliff:g> hari yang lalu"</item>
@@ -971,12 +817,9 @@
<item quantity="one" msgid="2178576254385739855">"esok"</item>
<item quantity="other" msgid="2973062968038355991">"dalam <xliff:g id="COUNT">%d</xliff:g> hari"</item>
</plurals>
- <!-- no translation found for preposition_for_date (9093949757757445117) -->
- <skip />
- <!-- no translation found for preposition_for_time (5506831244263083793) -->
- <skip />
- <!-- no translation found for preposition_for_year (5040395640711867177) -->
- <skip />
+ <string name="preposition_for_date" msgid="9093949757757445117">"pada <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="preposition_for_time" msgid="5506831244263083793">"pada <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="preposition_for_year" msgid="5040395640711867177">"dalam <xliff:g id="YEAR">%s</xliff:g>"</string>
<string name="day" msgid="8144195776058119424">"hari"</string>
<string name="days" msgid="4774547661021344602">"hari"</string>
<string name="hour" msgid="2126771916426189481">"jam"</string>
@@ -1004,34 +847,28 @@
<string name="cut" msgid="3092569408438626261">"Potong"</string>
<string name="copy" msgid="2681946229533511987">"Salin"</string>
<string name="paste" msgid="5629880836805036433">"Tampal"</string>
- <!-- no translation found for pasteDisabled (7259254654641456570) -->
- <skip />
+ <string name="pasteDisabled" msgid="7259254654641456570">"Tiada apa utk ditmpl"</string>
<string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
- <!-- no translation found for selectTextMode (6738556348861347240) -->
- <skip />
- <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
- <skip />
- <!-- no translation found for inputMethod (1653630062304567879) -->
- <skip />
- <!-- outdated translation 1672989176958581452 --> <string name="editTextMenuTitle" msgid="4909135564941815494">"Edit teks"</string>
+ <string name="selectTextMode" msgid="6738556348861347240">"Pilih teks..."</string>
+ <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
+ <string name="inputMethod" msgid="1653630062304567879">"Kaedah input"</string>
+ <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
<string name="low_internal_storage_view_title" msgid="1399732408701697546">"Kekurangan ruang"</string>
- <!-- outdated translation 635106544616378836 --> <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang simpanan telefon semakin habis."</string>
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang storan tablet semakin rendah."</string>
<string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Ruang simpanan telefon semakin habis."</string>
<string name="ok" msgid="5970060430562524910">"OK"</string>
<string name="cancel" msgid="6442560571259935130">"Batal"</string>
<string name="yes" msgid="5362982303337969312">"OK"</string>
<string name="no" msgid="5141531044935541497">"Batal"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"Perhatian"</string>
- <!-- no translation found for loading (1760724998928255250) -->
- <skip />
+ <string name="loading" msgid="1760724998928255250">"Memuatkan..."</string>
<string name="capital_on" msgid="1544682755514494298">"HIDUP"</string>
<string name="capital_off" msgid="6815870386972805832">"MATIKAN"</string>
<string name="whichApplication" msgid="4533185947064773386">"Selesaikan tindakan menggunakan"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakannya secara lalai untuk tindakan ini."</string>
<string name="clearDefaultHintMsg" msgid="4815455344600932173">"Padam bersih lalai dalam Tetapan Halaman Utama > Aplikasi > Urus aplikasi."</string>
<string name="chooseActivity" msgid="1009246475582238425">"Pilih tindakan"</string>
- <!-- no translation found for chooseUsbActivity (7892597146032121735) -->
- <skip />
+ <string name="chooseUsbActivity" msgid="7892597146032121735">"Pilih aplikasi untuk peranti USB"</string>
<string name="noApplications" msgid="1691104391758345586">"Tiada aplikasi yang boleh menjalankan tindakan ini."</string>
<string name="aerr_title" msgid="653922989522758100">"Maaf!"</string>
<string name="aerr_application" msgid="4683614104336409186">"Aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah berhenti secara tiba-tiba. Sila cuba lagi."</string>
@@ -1044,44 +881,30 @@
<string name="force_close" msgid="3653416315450806396">"Tutup paksa"</string>
<string name="report" msgid="4060218260984795706">"Laporkan"</string>
<string name="wait" msgid="7147118217226317732">"Tunggu"</string>
- <!-- no translation found for launch_warning_title (8323761616052121936) -->
- <skip />
- <!-- no translation found for launch_warning_replace (6202498949970281412) -->
- <skip />
- <!-- no translation found for launch_warning_original (188102023021668683) -->
- <skip />
+ <string name="launch_warning_title" msgid="8323761616052121936">"Aplikasi dihalakan semula"</string>
+ <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> kini sedang berjalan."</string>
+ <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> pada asalnya telah dilancarkan."</string>
<!-- no translation found for screen_compat_mode_scale (3202955667675944499) -->
<skip />
<!-- no translation found for screen_compat_mode_show (4013878876486655892) -->
<skip />
<!-- no translation found for screen_compat_mode_hint (2953716574198046484) -->
<skip />
- <!-- no translation found for smv_application (295583804361236288) -->
- <skip />
- <!-- no translation found for smv_process (5120397012047462446) -->
- <skip />
- <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
- <skip />
- <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
- <skip />
- <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
- <skip />
- <!-- no translation found for old_app_action (493129172238566282) -->
- <skip />
- <!-- no translation found for old_app_description (942967900237208466) -->
- <skip />
- <!-- no translation found for new_app_action (5472756926945440706) -->
- <skip />
- <!-- no translation found for new_app_description (6830398339826789493) -->
- <skip />
+ <string name="smv_application" msgid="295583804361236288">"Aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar dasar Mod Tegasnya sendiri."</string>
+ <string name="smv_process" msgid="5120397012047462446">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> telah melanggar dasar Mod Tegasnya sendiri."</string>
+ <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> dijalankan"</string>
+ <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Pilih untuk bertukar kepada aplikasi"</string>
+ <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Bertukar aplikasi?"</string>
+ <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Aplikasi lain sudah pun dijalankan yang mesti dihentikan sebelum anda boleh memulakan yang baru."</string>
+ <string name="old_app_action" msgid="493129172238566282">"Kembali ke <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="old_app_description" msgid="942967900237208466">"Jangan mulakan aplikasi baru."</string>
+ <string name="new_app_action" msgid="5472756926945440706">"Mulakan <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+ <string name="new_app_description" msgid="6830398339826789493">"Hentikan aplikasi lama tanpa menyimpan."</string>
<string name="sendText" msgid="5132506121645618310">"Pilih tindakan untuk teks"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Kelantangan pendering"</string>
<string name="volume_music" msgid="5421651157138628171">"Kelantangan media"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bermain melalui Bluetooth"</string>
- <!-- no translation found for volume_music_hint_silent_ringtone_selected (6158339745293431194) -->
- <skip />
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="6158339745293431194">"Nada dering senyap dipilih"</string>
<string name="volume_call" msgid="3941680041282788711">"Kelantangan semasa panggilan"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"Kelantangan semasa dalam panggilan menggunakan Bluetooth"</string>
<string name="volume_alarm" msgid="1985191616042689100">"Kelantangan penggera"</string>
@@ -1118,91 +941,77 @@
<skip />
<!-- no translation found for sim_restart_button (4722407842815232347) -->
<skip />
- <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
- <skip />
- <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
- <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tetapkan masa"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
<string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string>
<string name="default_permission_group" msgid="2690160991405646128">"Lalai"</string>
<string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string>
<string name="perms_hide" msgid="7283915391320676226"><b>"Sembunyikan"</b></string>
<string name="perms_show_all" msgid="2671791163933091180"><b>"Tunjukkan semua"</b></string>
- <!-- no translation found for usb_storage_activity_title (2399289999608900443) -->
- <skip />
+ <string name="usb_storage_activity_title" msgid="2399289999608900443">"Storan Massa USB"</string>
<string name="usb_storage_title" msgid="5901459041398751495">"sambungan USB"</string>
- <!-- outdated translation 2759542180575016871 --> <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Anda telah menyambungkan telefon anda ke komputer anda melalui USB. Pilih \"Lekap\" sekiranya anda mahu menyalin fail antara komputer anda dan kad SD telefon anda."</string>
- <!-- outdated translation 2759542180575016871 --> <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Anda telah menyambungkan telefon anda ke komputer anda melalui USB. Pilih \"Lekap\" sekiranya anda mahu menyalin fail antara komputer anda dan kad SD telefon anda."</string>
- <!-- outdated translation 8063426289195405456 --> <string name="usb_storage_button_mount" msgid="1052259930369508235">"Lekap"</string>
- <!-- outdated translation 2534784751603345363 --> <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Terdapat masalah menggunakan kad SD anda untuk storan USB."</string>
- <!-- outdated translation 2534784751603345363 --> <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Terdapat masalah menggunakan kad SD anda untuk storan USB."</string>
+ <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Anda telah bersambung kepada komputer anda melalui USB. Sentuh butang di bawah jika anda mahu menyalin fail antara komputer anda dan storan USB Android anda."</string>
+ <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Anda telah bersambung kepada komputer anda melalui USB. Sentuh butang di bawah jika anda mahu menyalin fail antara komputer anda dan kad SD Android anda."</string>
+ <string name="usb_storage_button_mount" msgid="1052259930369508235">"Hidupkan storan USB"</string>
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Terdapat masalah menggunakan storan USB anda untuk storan massa USB."</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Terdapat masalah menggunakan kad SD anda untuk storan massa USB."</string>
<string name="usb_storage_notification_title" msgid="8175892554757216525">"USB disambungkan"</string>
<string name="usb_storage_notification_message" msgid="7380082404288219341">"Pilih untuk menyalin fail ke/dari komputer anda."</string>
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Matikan storan USB"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Pilih untuk mematikan storan USB."</string>
- <!-- no translation found for usb_storage_stop_title (660129851708775853) -->
+ <string name="usb_storage_stop_title" msgid="660129851708775853">"Storan USB sedang digunakan"</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Sebelum mematikan storan USB, pastikan anda telah menyahlekap (“keluarkan”) storan USB Android anda daripada komputer anda."</string>
+ <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Sebelum mematikan storan USB, pastikan anda sudah menyahlekapkan (“mengeluarkan”) kad SD Android anda dari komputer anda."</string>
+ <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Matikan storan USB"</string>
+ <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Terdapat masalah mematikan storan USB. Semak untuk memastikan anda sudah menyahlekap hos USB, kemudian cuba lagi."</string>
+ <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Hidupkan storan USB."</string>
+ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika anda menghidupkan storan USB, sesetengah aplikasi yang anda sedang gunakan akan terhenti dan mungkin tidak akan tersedia sehingga anda memadamkan storan USB."</string>
+ <string name="dlg_error_title" msgid="8048999973837339174">"Pengendalian USB gagal"</string>
+ <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
<skip />
- <!-- no translation found for usb_storage_stop_message (1368842269463745067) -->
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
<skip />
- <!-- no translation found for usb_storage_stop_message (3613713396426604104) -->
- <skip />
- <!-- no translation found for usb_storage_stop_button_mount (7060218034900696029) -->
- <skip />
- <!-- no translation found for usb_storage_stop_error_message (143881914840412108) -->
- <skip />
- <!-- no translation found for dlg_confirm_kill_storage_users_title (963039033470478697) -->
- <skip />
- <!-- no translation found for dlg_confirm_kill_storage_users_text (3202838234780505886) -->
- <skip />
- <!-- no translation found for dlg_error_title (8048999973837339174) -->
- <skip />
- <!-- no translation found for dlg_ok (7376953167039865701) -->
- <skip />
- <!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format kad SD"</string>
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format storan USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kad SD"</string>
- <!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Adakah anda pasti ingin memformat kad SD? Semua data pada kad anda akan hilang."</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format storan USB, memadamkan semua fail yang disimpan? Tindakan tidak boleh dibalikkan!"</string>
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Adakah anda pasti ingin memformat kad SD? Semua data pada kad anda akan hilang."</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
- <!-- no translation found for adb_active_notification_title (6729044778949189918) -->
- <skip />
- <!-- no translation found for adb_active_notification_message (8470296818270110396) -->
- <skip />
- <!-- no translation found for select_input_method (6865512749462072765) -->
- <skip />
- <!-- no translation found for configure_input_methods (6324843080254191535) -->
- <skip />
+ <string name="adb_active_notification_title" msgid="6729044778949189918">"Penyahpepijatan USB disambungkan"</string>
+ <string name="adb_active_notification_message" msgid="8470296818270110396">"Pilih untuk melumpuhkan penyahpepijatan USB."</string>
+ <string name="select_input_method" msgid="6865512749462072765">"Pilih kaedah input"</string>
+ <string name="configure_input_methods" msgid="6324843080254191535">"Konfigurasikan kaedah input"</string>
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
- <!-- outdated translation 5457603418970994050 --> <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Menyediakan kad SD"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Menyediakan storan USB"</string>
<string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Menyediakan kad SD"</string>
<string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Menyemak untuk mengesan ralat."</string>
- <!-- outdated translation 780477838241212997 --> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Kad SD kosong"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Storan USB kosong"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Kad SD kosong"</string>
- <!-- outdated translation 3817704088027829380 --> <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Kad SD kosong atau mempunyai sistem fail yang tidak disokong."</string>
+ <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Storan USB kosong atau mempunyai sistem fail yang tidak disokong."</string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Kad SD kosong atau mempunyai sistem fail yang tidak disokong."</string>
- <!-- outdated translation 6410723906019100189 --> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Kad SD rosak"</string>
+ <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Storan USB rosak"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Kad SD rosak"</string>
- <!-- outdated translation 6902531775948238989 --> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Kad SD rosak. Anda mungkin perlu memformatkannya semula."</string>
+ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Storan USB rosak. Anda mungkin perlu memformatkannya semula."</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Kad SD rosak. Anda mungkin perlu memformatkannya semula."</string>
- <!-- outdated translation 6872152882604407837 --> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Kad SD dikeluarkan tanpa dijangka"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Strn USB dialh klr tnpa dijgka"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Kad SD dikeluarkan tanpa dijangka"</string>
- <!-- outdated translation 7260183293747448241 --> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Nyahlekap kad SD sebelum mengeluarkannya untuk mengelakkan kehilangan data."</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Nyahlekap storan USB sebelum mengeluarkannya untuk mengelakkan kehilangan data."</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Nyahlekap kad SD sebelum mengeluarkannya untuk mengelakkan kehilangan data."</string>
- <!-- outdated translation 6729801130790616200 --> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"selamat untuk mengeluarkan kad SD"</string>
+ <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Strn USB slamat utk dikluarkan"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"selamat untuk mengeluarkan kad SD"</string>
- <!-- outdated translation 568841278138377604 --> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Anda boleh mengeluarkan kad SD dengan selamat."</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Anda boleh mengeluarkan storan USB dengan selamat."</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Anda boleh mengeluarkan kad SD dengan selamat."</string>
- <!-- outdated translation 8902518030404381318 --> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Kad SD dikeluarkan"</string>
+ <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Storan USB dialih keluar"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Kad SD dikeluarkan"</string>
- <!-- outdated translation 3870120652983659641 --> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Kad SD telah dikeluarkan. Masukkan yang baru."</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Storan USB dikeluarkan. Sisipkan media baru."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Kad SD telah dikeluarkan. Masukkan yang baru."</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Tiada aktiviti yang sepadan ditemui"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"kemas kini statistik penggunaan komponen"</string>
<string name="permdesc_pkgUsageStats" msgid="891553695716752835">"Membenarkan pengubahsuaian statistik penggunaan komponen yang dikumpulkan. Bukan untuk kegunaan aplikasi biasa."</string>
- <!-- no translation found for permlab_copyProtectedData (1660908117394854464) -->
- <skip />
- <!-- no translation found for permdesc_copyProtectedData (537780957633976401) -->
- <skip />
+ <string name="permlab_copyProtectedData" msgid="1660908117394854464">"Membenarkan aplikasi menggunakan perkhidmatan bekas lalai untuk menyalin kandungan. Bukan untuk kegunaan aplikasi biasa."</string>
+ <string name="permdesc_copyProtectedData" msgid="537780957633976401">"Membenarkan aplikasi menggunakan perkhidmatan bekas lalai untuk menyalin kandungan. Bukan untuk kegunaan aplikasi biasa."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ketik dua kali untuk mendapatkan kawalan zum"</string>
<string name="gadget_host_error_inflating" msgid="2613287218853846830">"Ralat mengembungkan widget"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Pergi"</string>
@@ -1210,145 +1019,88 @@
<string name="ime_action_send" msgid="2316166556349314424">"Hantar"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Seterusnya"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Selesai"</string>
- <!-- no translation found for ime_action_previous (1443550039250105948) -->
- <skip />
+ <string name="ime_action_previous" msgid="1443550039250105948">"Sblm"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Laksanakan"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Dail nombor"\n"menggunakan <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Wujudkan kenalan"\n"menggunakan <xliff:g id="NUMBER">%s</xliff:g>"</string>
- <!-- no translation found for grant_credentials_permission_message_header (6824538733852821001) -->
+ <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"Satu atau lebih aplikasi berikut meminta kebenaran untuk mengakses akaun anda, sekarang dan pada masa hadapan."</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Adakah anda mahu membenarkan permintaan ini?"</string>
+ <string name="grant_permissions_header_text" msgid="2722567482180797717">"Permintaan Akses"</string>
+ <string name="allow" msgid="7225948811296386551">"Benarkan"</string>
+ <string name="deny" msgid="2081879885755434506">"Nafi"</string>
+ <string name="permission_request_notification_title" msgid="5390555465778213840">"Kebenaran Diminta"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="4325409589686688000">"Kebenaran Diminta"\n"untuk akaun <xliff:g id="ACCOUNT">%s</xliff:g>"</string>
+ <string name="input_method_binding_label" msgid="1283557179944992649">"Kaedah input"</string>
+ <string name="sync_binding_label" msgid="3687969138375092423">"Penyegerakan"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"Kebolehaksesan"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
+ <string name="pptp_vpn_description" msgid="2688045385181439401">"Protokol Penerowongan Titik Ke Titik"</string>
+ <string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol Penerowongan Lapisan ke-2"</string>
+ <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec berasaskan kunci prakongsi"</string>
+ <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec berasaskan sijil"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
<skip />
- <!-- no translation found for grant_credentials_permission_message_footer (3125211343379376561) -->
+ <!-- no translation found for vpn_title (5434034606697234123) -->
<skip />
- <!-- no translation found for grant_permissions_header_text (2722567482180797717) -->
+ <!-- no translation found for vpn_text (1610714069627824309) -->
<skip />
- <!-- no translation found for allow (7225948811296386551) -->
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
<skip />
- <!-- no translation found for deny (2081879885755434506) -->
- <skip />
- <!-- no translation found for permission_request_notification_title (5390555465778213840) -->
- <skip />
- <!-- no translation found for permission_request_notification_with_subtitle (4325409589686688000) -->
- <skip />
- <!-- no translation found for input_method_binding_label (1283557179944992649) -->
- <skip />
- <!-- no translation found for sync_binding_label (3687969138375092423) -->
- <skip />
- <!-- no translation found for accessibility_binding_label (4148120742096474641) -->
- <skip />
- <!-- no translation found for wallpaper_binding_label (1240087844304687662) -->
- <skip />
- <!-- no translation found for chooser_wallpaper (7873476199295190279) -->
- <skip />
- <!-- no translation found for pptp_vpn_description (2688045385181439401) -->
- <skip />
- <!-- no translation found for l2tp_vpn_description (3750692169378923304) -->
- <skip />
- <!-- no translation found for l2tp_ipsec_psk_vpn_description (3945043564008303239) -->
- <skip />
- <!-- no translation found for l2tp_ipsec_crt_vpn_description (5382714073103653577) -->
- <skip />
- <!-- no translation found for upload_file (2897957172366730416) -->
- <skip />
- <!-- no translation found for no_file_chosen (6363648562170759465) -->
- <skip />
- <!-- no translation found for reset (2448168080964209908) -->
- <skip />
- <!-- no translation found for submit (1602335572089911941) -->
- <skip />
- <!-- no translation found for car_mode_disable_notification_title (3164768212003864316) -->
- <skip />
- <!-- no translation found for car_mode_disable_notification_message (668663626721675614) -->
- <skip />
- <!-- no translation found for tethered_notification_title (3146694234398202601) -->
- <skip />
- <!-- no translation found for tethered_notification_message (3067108323903048927) -->
- <skip />
- <!-- no translation found for back_button_label (2300470004503343439) -->
- <skip />
- <!-- no translation found for next_button_label (1080555104677992408) -->
- <skip />
- <!-- no translation found for skip_button_label (1275362299471631819) -->
- <skip />
- <!-- no translation found for throttle_warning_notification_title (4890894267454867276) -->
- <skip />
- <!-- no translation found for throttle_warning_notification_message (2609734763845705708) -->
- <skip />
- <!-- no translation found for throttled_notification_title (6269541897729781332) -->
- <skip />
- <!-- no translation found for throttled_notification_message (4712369856601275146) -->
- <skip />
- <!-- no translation found for no_matches (8129421908915840737) -->
- <skip />
- <!-- no translation found for find_on_page (1946799233822820384) -->
- <skip />
- <!-- no translation found for matches_found:one (8167147081136579439) -->
- <!-- no translation found for matches_found:other (4641872797067609177) -->
- <!-- no translation found for action_mode_done (7217581640461922289) -->
- <skip />
- <!-- no translation found for progress_unmounting (535863554318797377) -->
- <skip />
- <!-- no translation found for progress_unmounting (5556813978958789471) -->
- <skip />
- <!-- no translation found for progress_erasing (4183664626203056915) -->
- <skip />
- <!-- no translation found for progress_erasing (2115214724367534095) -->
- <skip />
- <!-- no translation found for format_error (4320339096529911637) -->
- <skip />
- <!-- no translation found for format_error (1343380371925238343) -->
- <skip />
- <!-- no translation found for media_bad_removal (7960864061016603281) -->
- <skip />
- <!-- no translation found for media_checking (418188720009569693) -->
- <skip />
- <!-- no translation found for media_checking (7334762503904827481) -->
- <skip />
- <!-- no translation found for media_removed (7001526905057952097) -->
- <skip />
- <!-- no translation found for media_shared (5830814349250834225) -->
- <skip />
- <!-- no translation found for media_shared (5706130568133540435) -->
- <skip />
- <!-- no translation found for media_unknown_state (729192782197290385) -->
- <skip />
- <!-- no translation found for share (1778686618230011964) -->
- <skip />
- <!-- no translation found for find (4808270900322985960) -->
- <skip />
- <!-- no translation found for websearch (4337157977400211589) -->
- <skip />
- <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
- <skip />
- <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
- <skip />
- <!-- no translation found for gpsNotifMessage (1374718023224000702) -->
- <skip />
- <!-- no translation found for gpsVerifYes (2346566072867213563) -->
- <skip />
- <!-- no translation found for gpsVerifNo (1146564937346454865) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
- <skip />
- <!-- no translation found for sync_really_delete (8933566316059338692) -->
- <skip />
- <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
- <skip />
- <!-- no translation found for sync_do_nothing (8717589462945226869) -->
- <skip />
- <!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
- <skip />
- <!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
- <skip />
- <!-- no translation found for vpn_notification_hint_disconnected (4689796928510104200) -->
- <skip />
- <!-- no translation found for choose_account_label (4191313562041125787) -->
- <skip />
- <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
- <skip />
- <!-- no translation found for number_picker_decrement_button (2576606679160067262) -->
- <skip />
+ <string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
+ <string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
+ <string name="submit" msgid="1602335572089911941">"Serah"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mod kereta didayakan"</string>
+ <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Pilih untuk keluar daripada mod kereta."</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"Penambatan atau titik panas aktif"</string>
+ <string name="tethered_notification_message" msgid="3067108323903048927">"Sentuh untuk mengkonfigurasikan"</string>
+ <string name="back_button_label" msgid="2300470004503343439">"Kembali"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"Seterusnya"</string>
+ <string name="skip_button_label" msgid="1275362299471631819">"Langkau"</string>
+ <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Penggunaan tinggi data mudah alih"</string>
+ <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Sentuh untuk mengetahui lebih lanjut mengenai penggunaan data"</string>
+ <string name="throttled_notification_title" msgid="6269541897729781332">"Melebihi had data mudah alih"</string>
+ <string name="throttled_notification_message" msgid="4712369856601275146">"Sentuh untuk mengetahui lebih lanjut mengenai penggunaan data mudah alih"</string>
+ <string name="no_matches" msgid="8129421908915840737">"Tiada padanan"</string>
+ <string name="find_on_page" msgid="1946799233822820384">"Cari di halaman"</string>
+ <plurals name="matches_found">
+ <item quantity="one" msgid="8167147081136579439">"1 padanan"</item>
+ <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> dari <xliff:g id="TOTAL">%d</xliff:g>"</item>
+ </plurals>
+ <string name="action_mode_done" msgid="7217581640461922289">"Selesai"</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Menyahlekap storan USB..."</string>
+ <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Menyahlekap kad SD..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Memadam storan USB..."</string>
+ <string name="progress_erasing" product="default" msgid="2115214724367534095">"Memadam kad SD..."</string>
+ <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Gagal memadam storan USB."</string>
+ <string name="format_error" product="default" msgid="1343380371925238343">"Gagal memadamkan kad SD."</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"Kad SD telah dikeluarkan sebelum dinyahlekap."</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Storan USB sedang disemak buat masa ini."</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"Kad SD sedang disemak buat masa ini."</string>
+ <string name="media_removed" msgid="7001526905057952097">"Kad SD telah dikeluarkan."</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Storan USB sedang digunakan oleh komputer buat masa ini."</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"Kad SD sedang digunakan oleh komputer buat masa ini."</string>
+ <string name="media_unknown_state" msgid="729192782197290385">"Media luaran dalam keadaan yang tidak diketahui."</string>
+ <string name="share" msgid="1778686618230011964">"Kongsi"</string>
+ <string name="find" msgid="4808270900322985960">"Cari"</string>
+ <string name="websearch" msgid="4337157977400211589">"Carian Web"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Permintaan lokasi daripada <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Permintaan lokasi"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"Diminta oleh <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"Ya"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"Tidak"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"Melebihi had padam"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"Terdapat <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> item yang dipadamkan untuk <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, akaun <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Apakah yang ingin anda lakukan?"</string>
+ <string name="sync_really_delete" msgid="8933566316059338692">"Padam item."</string>
+ <string name="sync_undo_deletes" msgid="8610996708225006328">"Buat asal pemadaman."</string>
+ <string name="sync_do_nothing" msgid="8717589462945226869">"Jangan lakukan apa-apa sekarang."</string>
+ <string name="vpn_notification_title_connected" msgid="3197819122581348515">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> disambungkan"</string>
+ <string name="vpn_notification_title_disconnected" msgid="4614192702448522822">"VPN <xliff:g id="PROFILENAME">%s</xliff:g> diputuskan sambungannya"</string>
+ <string name="vpn_notification_hint_disconnected" msgid="4689796928510104200">"Sentuh untuk menyambung semula ke VPN."</string>
+ <string name="choose_account_label" msgid="4191313562041125787">"Pilih akaun"</string>
+ <string name="number_picker_increment_button" msgid="4830170763103463443">"Kenaikan"</string>
+ <string name="number_picker_decrement_button" msgid="2576606679160067262">"Penyusutan"</string>
<!-- no translation found for action_bar_home_description (5293600496601490216) -->
<skip />
<!-- no translation found for action_bar_up_description (2237496562952152589) -->
@@ -1363,4 +1115,26 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Sijil keselamatan"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sijil ini sah."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Dikeluarkan kepada:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nama biasa:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisasi:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unit Organisasi:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Dikeluarkan oleh:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Kesahan:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Dikeluarkan pada:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Tamat tempoh pada:"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 2413685..aca95fd 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK-koden du skrev inn er feil."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN-kodene stemmer ikke overens."</string>
<string name="invalidPin" msgid="3850018445187475377">"PIN-koden må være mellom fire og åtte siffer."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Skriv inn en PUK-kode på åtte tall eller mer."</string>
<string name="needPuk" msgid="919668385956251611">"SIM-kortet ditt er PUK-låst. Skriv inn PUK-koden for å låse det opp."</string>
<string name="needPuk2" msgid="4526033371987193070">"Skriv inn PUK2 for å låse opp SIM-kortet."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Inngående nummervisning"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flymodus"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flymodus er på"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flymodus er av"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"Over 100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Over 100"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Betaltjenester"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Lar applikasjonen motta og behandle SMS-meldinger. Ondsinnede applikasjoner kan overvåke meldinger eller slette dem uten at de vises."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"motta MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Lar applikasjonen motta og behandle MMS-meldinger. Ondsinnede applikasjoner kan overvåke meldinger eller slette dem uten at de vises."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"motta nødkringkastinger"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Tillater applikasjonen å motta og behandle nødkringkastingsmeldinger. Denne tillatelsen er kun tilgjengelig for systemapplikasjoner."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"sende SMS-meldinger"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Lar applikasjonen sende SMS-meldinger. Ondsinnede applikasjoner kan koste deg penger ved å sende meldinger uten bekreftelse."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"lese SMS- og MMS-meldinger"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Lar applikasjonen tvinge enhver aktivitet som er i forgrunnen til å lukkes og gå tilbake. Vanlige applikasjoner bør aldri trenge dette."</string>
<string name="permlab_dump" msgid="1681799862438954752">"hente intern systemtilstand"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Lar applikasjonen hente intern tilstand fra systemet. Ondsinnede applikasjoner kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hent av skjerminnhold"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Tillater applikasjonen å hente innholdet i det aktive vinduet. Skadelige applikasjoner kan hente hele vindusinnholdet og gå gjennom all teksten, unntatt passord."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Tillater innehaveren å sende hensikter til enhetsadministrator. Bør aldri være nødvendig for normale programmer."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"snu skjermen"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Lar applikasjonen rotere skjermen når som helst. Vanlige applikasjoner bør aldri trenge dette."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"endre pekerhastighet"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Tillater at en applikasjon endrer hastigheten til musen eller styreflatepekeren til enhver tid. Skal aldri være nødvendig ved normal bruk."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"sende Linux-signaler til applikasjoner"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Lar applikasjonen spørre om at et gitt signal blir sendt til alle varige prosesser."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"forbli kjørende"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"skrive kontaktinformasjon"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lar programmet endre kontaktinformasjon (adresser) lagret på nettbrettet. Skadelige programmet kan bruke dette til å slette eller endre kontaktinformasjonen."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Lar applikasjonen endre kontakt- og adresseinformasjon lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å redigere eller endre kontaktinformasjonen."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"les kalenderaktiviteter"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lar programmet lese alle kalenderhendelser lagret på nettbrettet. Skadelige programmer kan bruke dette til å sende kalenderhendelsene dine til andre."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Lar applikasjonen lese alle kalenderhendelser lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å sende kalenderhendelser til andre."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontroller overføring av data med NFC-teknologi"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Tillater programmet å kommunisere data via koder, kort og lesere for NFC-teknologi."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"fange opp og endre all nettverkstrafikk"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Lar en applikasjon fange opp og kontrollere all nettverkstrafikk, for eksempel for å etablere en VPN-tilkobling. Skadelige applikasjoner kan overvåke, omdirigere eller endre nettverkspakker uten at du vet om det."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Lar en applikasjon fange opp og kontrollere all nettverkstrafikk for å etablere en VPN-tilkobling. Skadelige applikasjoner kan overvåke, omdirigere eller endre nettverkspakker uten at du vet om det."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"slå av tastaturlås"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lar applikasjonen slå av tastaturlåsen og enhver tilknyttet passordsikkerhet. Et legitimt eksempel på dette er at telefonen slår av tastaturlåsen når den mottar et innkommende anrop, og så slår den på igjen når samtalen er over."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillater et program å lese og skrive til bufrede filer."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"foreta/motta Internett-anrop"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Tillater et program å bruke SIP-tjenesten til å foreta og motta Internett-anrop."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontroller tillatt lengde og tegn i passord for opplåsing av skjerm"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Velg hvor lenge det skal gå før passordet til skjermlåsen må byttes"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angi lagringskryptering"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Krever at lagrede programdata krypteres"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Hjemmenummer"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbeid"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Annen"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Skriv inn PIN-kode:"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Tast inn PUK-kode og ny personlig kode"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Ny personlig kode"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Trykk og oppgi passord"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Skriv inn passord for å låse opp"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Skriv inn personlig kode for å låse opp"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Ikke noe SIM-kort i telefonen."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sett inn et SIM-kort."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Kun nødanrop"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Nettverk ikke tillatt"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet er PUK-låst."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Hvis du aktiverer USB-lagring, virker ikke lenger enkelte av programmene du bruker, og de kan være utilgjengelige inntil du deaktiverer USB-lagringen."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-operasjonen mislyktes"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formaterer USB-lagring"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatere minnekort"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vil du formatere USB-lagring og slette alle lagrede filer? Handlingen kan ikke angres!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Lag 2-tunneleringsprotokoll"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Passordbasert L2TP/IPSec-VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikatbasert L2TP/IPSec-VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Velg fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
<string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Intern lagring"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Rediger"</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Sikkerhetssertifikat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Sertifikatet er gyldig."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Utstedt til:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Ordinært navn:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisasjon:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisasjonsenhet:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Utstedt av:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Gyldighet:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Utstedt:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Utløper den:"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index dbb7e98..5fe75fc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"De PUK-code die u heeft ingevoerd, is onjuist."</string>
<string name="mismatchPin" msgid="3695902225843339274">"De PIN-codes die u heeft ingevoerd, komen niet overeen."</string>
<string name="invalidPin" msgid="3850018445187475377">"Voer een PIN-code van 4 tot 8 cijfers in."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Typ een PUK-code die 8 cijfers of langer is."</string>
<string name="needPuk" msgid="919668385956251611">"Uw SIM-kaart is vergrendeld met de PUK-code. Typ de PUK-code om te ontgrendelen."</string>
<string name="needPuk2" msgid="4526033371987193070">"Voer de PUK2-code in om de SIM-kaart te ontgrendelen."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Inkomende beller-id"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegmodus"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegmodus is AAN"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegmodus is UIT"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services waarvoor u moet betalen"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Hiermee kan een app SMS-berichten ontvangen en verwerken. Schadelijke apps kunnen uw berichten bijhouden of deze verwijderen zonder dat u ze te zien krijgt."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMS ontvangen"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Hiermee kan een app MMS-berichten ontvangen en verwerken. Schadelijke apps kunnen uw berichten bijhouden of deze verwijderen zonder dat u ze te zien krijgt."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"noodberichten ontvangen"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Hiermee kan een app noodberichten ontvangen en verwerken. Deze toestemming is alleen beschikbaar voor systeemapps."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"SMS-berichten verzenden"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Hiermee kan de app SMS-berichten verzenden. Schadelijke apps kunnen u geld kosten door berichten te verzenden zonder uw toestemming."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMS of MMS lezen"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Hiermee kan een app elke willekeurige activiteit die op de voorgrond wordt uitgevoerd, sluiten en naar de achtergrond verplaatsen. Nooit vereist voor normale apps."</string>
<string name="permlab_dump" msgid="1681799862438954752">"interne systeemstatus ophalen"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Hiermee kan een app de interne status van het systeem ophalen. Schadelijke apps kunnen privé- of veiligheidsgegevens ophalen die ze normaal niet nodig hebben."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"scherminhoud ophalen"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Hiermee kan een app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen toepassingen voorkomen"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Staat de houder toe intenties te verzenden naar een apparaatbeheerder. Nooit vereist voor normale toepassingen."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"schermstand wijzigen"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Hiermee kan een app op elk gewenst moment de oriëntatie van het scherm wijzigen. Nooit vereist voor normale apps."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"aanwijzersnelheid wijzigen"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Hiermee kan een app de snelheid van de muis- of trackpadaanwijzer op elk moment wijzigen. Dit zou voor normale apps niet nodig moeten zijn."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"Linux-signalen verzenden naar toepassingen"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Hiermee kan de app ervoor zorgen dat het geleverde signaal wordt verzonden naar alle persistente processen."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"app altijd laten uitvoeren"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"contactgegevens schrijven"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Hiermee kan een app de op uw tablet opgeslagen contactgegevens (adresgegevens) wijzigen. Schadelijke apps kunnen hiermee uw contactgegevens verwijderen of wijzigen."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Hiermee kan een app de op uw telefoon opgeslagen contactgegevens (adresgegevens) wijzigen. Schadelijke apps kunnen hiermee uw contactgegevens verwijderen of wijzigen."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"agendagebeurtenissen lezen"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Hiermee kan een app alle agendagebeurtenissen lezen die zijn opgeslagen op uw tablet. Schadelijke apps kunnen hiervan gebruik maken om uw agendagebeurtenissen te verzenden naar andere personen."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Hiermee kan een app alle agendagebeurtenissen lezen die zijn opgeslagen op uw telefoon. Schadelijke apps kunnen hiervan gebruik maken om uw agendagebeurtenissen te verzenden naar andere personen."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"Near Field Communication regelen"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Hiermee kan een app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"alle netwerkverkeer onderscheppen en aanpassen"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Hiermee kan een app alle netwerkverkeer onderscheppen en controleren, bijvoorbeeld om een VPN-verbinding tot stand te brengen. Schadelijke apps kunnen netwerkpakketten controleren, omleiden of aanpassen zonder uw medeweten."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Hiermee kan een app alle netwerkverkeer onderscheppen en controleren om een VPN-verbinding tot stand te brengen. Schadelijke apps kunnen netwerkpakketten controleren, omleiden of aanpassen zonder uw medeweten."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"toetsvergrendeling uitschakelen"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Hiermee kan een app de toetsvergrendeling en bijbehorende wachtwoordbeveiliging uitschakelen. Een voorbeeld: de telefoon schakelt de toetsvergrendeling uit wanneer een oproep binnenkomt en schakelt de toetsvergrendeling weer in zodra de oproep wordt beëindigd."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Staat een app toe het cachebestandssysteem te lezen en te schrijven."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"internetoproepen starten/ontvangen"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Hiermee kan een app de SIP-service gebruiken om internetoproepen te starten/te ontvangen."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Beheren hoe vaak het wachtwoord voor schermvergrendeling moet worden gewijzigd"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Codering voor opslag instellen"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vereisen dat opgeslagen toepassingsgegevens kunnen worden gecodeerd"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Thuis"</item>
<item msgid="869923650527136615">"Mobiel"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Overig"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN-code invoeren"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Geef de PUK-code en de nieuwe pincode op"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-code"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nieuwe pincode"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Raak aan om wachtwoord op te geven"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Voer het wachtwoord in om te ontgrendelen"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Voer de PIN-code in om te ontgrendelen"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Geen SIM-kaart in telefoon."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Plaats een SIM-kaart."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Alleen noodoproepen"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Netwerk vergrendeld"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kaart is vergrendeld met PUK-code."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Als u USB-opslag inschakelt, worden bepaalde toepassingen die u gebruikt, gestopt en worden deze mogelijk pas weer beschikbaar wanneer u USB-opslag uitschakelt."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-bewerking mislukt"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB-opslag formatt."</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kaart formatteren"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB-opslag formatteren en alle opgeslagen bestanden wissen? Actie kan niet ongedaan worden gemaakt."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol (L2TP)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Vooraf gedeelde sleutel op basis van L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certificaat op basis van L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string>
<string name="reset" msgid="2448168080964209908">"Opnieuw instellen"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Interne opslag"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kaart"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-opslag"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Bewerken..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Beveiligingscertificaat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Dit certificaat is geldig."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Uitgegeven voor:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Algemene naam:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisatie:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisatie-eenheid:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Uitgegeven door:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Geldigheid:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Uitgegeven op:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Verloopt op:"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 36d3cdd..0221da7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Wprowadzony kod PUK jest nieprawidłowy."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Wprowadzone kody PIN nie są identyczne."</string>
<string name="invalidPin" msgid="3850018445187475377">"Wpisz kod PIN o długości od 4 do 8 cyfr."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Wpisz kod PUK składający się z co najmniej 8 cyfr."</string>
<string name="needPuk" msgid="919668385956251611">"Karta SIM jest zablokowana kodem PUK. Wprowadź kod PUK, aby odblokować kartę."</string>
<string name="needPuk2" msgid="4526033371987193070">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Identyfikator rozmówcy przy połączeniach przychodzących"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Tryb samolotowy"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Tryb samolotowy jest włączony"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Tryb samolotowy jest wyłączony"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
<string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usługi płatne"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Pozwala aplikacjom na odbieranie i przetwarzanie wiadomości SMS. Szkodliwe aplikacje mogą monitorować wiadomości lub usuwać je bez wyświetlania ich użytkownikowi."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"odbieranie wiadomości MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Pozwala aplikacji na odbieranie i przetwarzanie wiadomości MMS. Szkodliwe aplikacje mogą monitorować wiadomości lub usuwać je bez pokazywania ich użytkownikowi."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"odbiór emisji alarmowych"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Umożliwia aplikacji odbiór i przetwarzanie wiadomości pochodzących z emisji alarmowych. To pozwolenie jest dostępne tylko dla aplikacji systemowych."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"wysyłanie wiadomości SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Pozwól aplikacjom na wysyłanie wiadomości SMS. Szkodliwe aplikacje mogą generować koszty, wysyłając wiadomości bez wiedzy użytkownika."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"czytanie wiadomości SMS lub MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Pozwala aplikacji na wymuszenie zamknięcia i cofnięcia dowolnej operacji działającej na pierwszym planie. Nigdy nie powinno być potrzebne normalnym aplikacjom."</string>
<string name="permlab_dump" msgid="1681799862438954752">"pobieranie informacji o wewnętrznym stanie systemu"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Pozwala aplikacjom na pobieranie informacji o wewnętrznym stanie systemu. Szkodliwe aplikacje mogą pobrać szeroką gamę osobistych i zabezpieczonych informacji, które normalnie nie powinny im być nigdy potrzebne."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"pobieranie zawartości ekranu"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Umożliwia aplikacji pobieranie zawartości aktywnego okna. Złośliwe aplikacje mogą pobrać całą zawartość okna i analizować cały tekst, z wyjątkiem haseł."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"częściowe wyłączenie"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Zezwala posiadaczowi na wysyłanie informacji o zamiarach do administratora urządzenia. Opcja nie powinna być nigdy potrzebna w przypadku zwykłych aplikacji."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"zmienianie orientacji ekranu"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Pozwala aplikacji na zmianę orientacji ekranu w dowolnym momencie. Nigdy nie powinno być potrzeby stosowania w normalnych aplikacjach."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmiana szybkości wskaźnika"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Umożliwia aplikacji zmianę szybkości poruszania wskaźnikiem myszy lub panelu dotykowego w dowolnym momencie. Nie powinno to być nigdy wymagane przez zwykłe aplikacje."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"wysyłanie sygnałów systemu Linux do aplikacji"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Pozwala aplikacjom żądać, aby dostarczany sygnał był wysyłany do wszystkich trwających procesów."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"sprawianie, że aplikacja jest cały czas uruchomiona"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"zapisywanie danych kontaktowych"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Zezwala aplikacji na modyfikowanie danych kontaktowych (adresów) zapisanych w tablecie. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu usunięcia lub zmodyfikowania danych kontaktowych."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Pozwala aplikacji na zmianę danych kontaktowych (adresowych) zapisanych w telefonie. Szkodliwe aplikacje mogą to wykorzystać, aby usunąć lub zmienić dane kontaktowe."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"odczytywanie wydarzeń w kalendarzu"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Zezwala aplikacji na odczyt wszystkich wydarzeń z kalendarza zapisanych w tablecie. Złośliwe aplikacje mogą wykorzystać tę możliwość w celu wysłania wydarzeń z kalendarza do innych osób."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Pozwala aplikacji na odczytywanie wszystkich wydarzeń z kalendarza, zapisanych w telefonie. Szkodliwe aplikacje mogą to wykorzystać do rozsyłania wydarzeń z kalendarza do innych ludzi."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontrolowanie łączności Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Zezwala aplikacji na komunikowanie się z użyciem tagów, kart i czytników Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"przechwytywanie i modyfikowanie całego ruchu sieciowego"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Zezwala aplikacji na przechwytywanie i kontrolę całego ruchu sieciowego, np. w celu nawiązania połączenia w sieci VPN. Złośliwe aplikacje mogą monitorować, przekierowywać lub modyfikować pakiety sieciowe bez wiedzy użytkownika."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Zezwala aplikacji na przechwytywanie i kontrolę całego ruchu sieciowego w celu nawiązania połączenia z siecią VPN. Złośliwe aplikacje mogą monitorować, przekierowywać lub modyfikować pakiety sieciowe bez Twojej wiedzy."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"wyłączanie blokady klawiatury"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Typowym przykładem takiego działania jest wyłączanie blokady klawiatury, gdy pojawia się połączenie przychodzące, a następnie ponowne jej włączanie po zakończeniu połączenia."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizowania"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Zezwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"nawiązywanie/odbieranie połączeń przez internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Umożliwia aplikacji korzystanie z usługi SIP do nawiązywania/odbierania połączeń przez internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrola częstości zmian hasła ekranu blokady"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustaw szyfrowanie pamięci"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Wymaga szyfrowania danych zapisanych aplikacji"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Dom"</item>
<item msgid="869923650527136615">"Komórka"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Służbowy"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Inny"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Wprowadź kod PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Wpisz kod PUK i nowy kod PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kod PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nowy kod PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Dotknij, aby podać hasło"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Wprowadź hasło, aby odblokować"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Wprowadź kod PIN, aby odblokować"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Brak karty SIM w telefonie."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Włóż kartę SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Tylko połączenia alarmowe"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Sieć zablokowana"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM jest zablokowana kodem PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Po włączeniu nośnika USB niektóre używane aplikacje zostaną zatrzymane i mogą być niedostępne do chwili wyłączenia nośnika USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operacja USB nie powiodła się"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatuj nośnik USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuj kartę SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Czy sformatować nośnik USB i wymazać wszystkie zapisane na nim pliki? Tej czynności nie można cofnąć."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokół L2TP"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Sieć VPN L2TP/IPSec z kluczem PSK"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sieć VPN L2TP/IPSec z certyfikatem"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string>
<string name="reset" msgid="2448168080964209908">"Resetuj"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Pamięć wewnętrzna"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Nośnik USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Edytuj..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certyfikat zabezpieczeń"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Ten certyfikat jest prawidłowy."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Otrzymujący:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nazwa pospolita:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizacja:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Jednostka organizacyjna:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Wystawca:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Poprawność:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Data wystawienia:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Wygasa:"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 9cec4b6..4972e56 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"O PUK que introduziu não está correcto."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Os PINs que introduziu não coincidem."</string>
<string name="invalidPin" msgid="3850018445187475377">"Introduza um PIN entre 4 e 8 números."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Introduza um PUK que tenha 8 ou mais algarismos."</string>
<string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID do Autor da Chamada"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo de voo está activado"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo de voo está desactivado"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que implicam pagamento"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permite à aplicação receber e processar mensagens SMS. Algumas aplicações maliciosas podem monitorizar as suas mensagens e eliminá-las sem mostrá-las a si."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"receber MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permite à aplicação receber e processar mensagens MMS. Algumas aplicações maliciosas podem monitorizar as mensagens ou eliminá-las sem mostrá-las ao utilizador."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"receber transmissões de emergência"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permite que uma aplicação obtenha e processe mensagens de transmissões de emergência. Esta autorização só está disponível para aplicações do sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar mensagens SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permite à aplicação enviar mensagens SMS. Algumas aplicações maliciosas podem fazer com que incorra em custos, enviando mensagens sem a sua confirmação."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"ler SMS ou MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permite a uma aplicação forçar qualquer actividade em primeiro plano a fechar e retroceder. Nunca deve ser necessário para aplicações normais."</string>
<string name="permlab_dump" msgid="1681799862438954752">"obter estado interno do sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permite à aplicação obter o estado interno do sistema. Algumas aplicações maliciosas podem obter uma ampla variedade de dados privados e seguros de que, normalmente, nunca devem necessitar."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"obter o conteúdo do ecrã"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permite que uma aplicação obtenha o conteúdo da janela ativa. As aplicações maliciosas poderão obter todo o conteúdo da janela e examinar todo o texto nela contida, exceto palavras-passe."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"encerramento parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gestor de actividade num estado de encerramento. Não executa um encerramento completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite ao titular enviar intenções para um administrador do dispositivo. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"mudar orientação do ecrã"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permite a uma aplicação mudar a rotação do ecrã em qualquer momento. Nunca deve ser necessário para aplicações normais."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar a veloc. do ponteiro"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permite que uma aplicação mude a velocidade do ponteiro do rato ou do trackpad a qualquer momento. Não deverá ser necessário em aplicações normais."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"enviar sinais Linux para aplicações"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permite à aplicação pedir que o sinal fornecido seja enviado a todos os processos persistentes."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"fazer com que a aplicação seja sempre executada"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"escrever dados de contacto"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite a uma aplicação modificar os dados de contacto (endereço) armazenados no seu tablet. Algumas aplicações maliciosas podem utilizar estes dados para apagar ou modificar os dados dos seus contactos."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite a uma aplicação modificar os dados de contacto (endereço) armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar estes dados para apagar ou modificar os dados dos seus contactos."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"ler eventos da agenda"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite a uma aplicação ler todos os eventos do calendário armazenados no seu tablet. Algumas aplicações maliciosas podem utilizar este item para enviar os eventos do seu calendário a outras pessoas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite a uma aplicação ler todos os eventos do calendário armazenados no seu telefone. Algumas aplicações maliciosas podem utilizar este item para enviar os eventos do seu calendário a outras pessoas."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlo Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite que uma aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"intercetar e modificar todo o tráfego de rede"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">" ou modificar os pacotes de rede sem o seu conhecimento."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permite que uma aplicação intercete e inspecione todo o tráfego de rede para estabelecer uma ligação VPN. As aplicações maliciosas podem monitorizar, reencaminhar ou modificar pacotes de rede sem o seu conhecimento."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar bloqueio de teclas"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite a uma aplicação desactivar o bloqueio de teclas e qualquer segurança por palavra-passe associada. Um exemplo legítimo é a desactivação do bloqueio de teclas pelo telefone ao receber uma chamada, reactivando, em seguida, o bloqueio de teclas ao terminar a chamada."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite a uma aplicação ler e escrever no sistema de ficheiros da cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Autoriza uma aplicação a utilizar o serviço SIP para fazer/receber chamadas pela internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a palavra-passe deve ser alterada"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Def. encriptação armazenamento"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Requerer encriptação dos dados da aplicação armazenados"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Residência"</item>
<item msgid="869923650527136615">"Móvel"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Emprego"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduzir código PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Introduza o PUK e o novo código PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Novo Código PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Toque introduzir palavra-passe"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduza a palavra-passe para desbloquear"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introduza o PIN para desbloquear"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nenhum cartão SIM no tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Nenhum cartão SIM no telefone."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Introduza um cartão SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Apenas chamadas de emergência"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado por PUK"</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se activar o armazenamento USB, algumas aplicações que estiver a utilizar serão paradas e poderão ficar indisponíveis até desactivar o armazenamento USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Falha na operação USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar armazenamento USB e apagar todos os ficheiros armazenados? Não é possível reverter a acção!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de túnel de camada 2 (L2TP)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec baseada em chave pré- partilhada"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec baseada em certificado"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Não foi seleccionado nenhum ficheiro"</string>
<string name="reset" msgid="2448168080964209908">"Repor"</string>
@@ -1051,6 +1093,17 @@
<string name="storage_internal" msgid="7556050805474115618">"Armazenamento Interno"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Cartão SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
<skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 57737c9..09f0876 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"O PUK digitado não está correto."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Os PINs digitados não correspondem."</string>
<string name="invalidPin" msgid="3850018445187475377">"Digite um PIN com 4 a 8 números."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Digite um PUK com oito números ou mais."</string>
<string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
<string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o cartão SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID do chamador de entrada"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo de avião ATIVADO"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo de avião DESATIVADO"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"Mais de cem"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Mais de cem"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permite que o aplicativo receba e processe mensagens SMS. Aplicativos maliciosos podem monitorar as suas mensagens ou excluí-las sem mostrá-las a você."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"receber MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permite que o aplicativo receba e processe mensagens MMS. Aplicativos maliciosos podem monitorar as suas mensagens ou excluí-las sem mostrá-las a você."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"receber transmissões de emergência"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permite que o aplicativo receba e processe mensagens de transmissão de emergência. Esta permissão está disponível somente para aplicativos do sistema."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"enviar mensagens SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permite que o aplicativo envie mensagens SMS. Aplicativos maliciosos podem gerar gastos enviando mensagens sem a sua confirmação."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"ler SMS ou MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permite que um aplicativo force o fechamento de qualquer atividade que esteja em primeiro plano. Aplicativos normais não devem precisar disso em momento algum."</string>
<string name="permlab_dump" msgid="1681799862438954752">"recuperar o estado interno do sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permite que um aplicativo recupere o estado interno do sistema. Aplicativos maliciosos podem recuperar uma grande variedade de informações privadas e de segurança que normalmente não precisariam."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"recuperar conteúdo da tela"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permite que o aplicativo recupere o conteúdo da janela ativa. Aplicativos maliciosos podem recuperar todo o conteúdo da janela e analisar todo o texto, exceto as senhas."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"desligamento parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gerenciador de atividades em um estado de desligamento. Não executa o desligamento completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite que o detentor envie tentativas ao administrador de um dispositivo. Não é necessário para aplicativos normais."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"alterar orientação da tela"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permite que um aplicativo altere a rotação da tela a qualquer momento. Aplicativos normais não devem precisar disso em momento algum."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar velocidade do ponteiro"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permite que um aplicativo altere a velocidade do ponteiro do mouse ou do trackpad a qualquer momento. Nunca será necessário para aplicativos normais."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"enviar sinais de Linux para os aplicativos"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permite que o aplicativo solicite que o sinal fornecido seja enviado a todos os processos persistentes."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"executar sempre o aplicativo"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"gravar dados de contato"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite que um aplicativo modifique os dados de contato (endereço) armazenados em seu tablet. Aplicativos maliciosos podem usar isso para apagar ou modificar seus dados de contato."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite que um aplicativo modifique os dados de contato (endereço) armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os seus dados de contato."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"ler eventos da agenda"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite que um aplicativo leia todos os eventos da agenda armazenados em seu tablet. Aplicativos maliciosos podem usar isso para enviar eventos de sua agenda para outras pessoas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite que um aplicativo leia todos os eventos da agenda armazenados no seu telefone. Aplicativos maliciosos podem usar isso para enviar eventos da sua agenda para outras pessoas."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlar a comunicação a curta distância"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite que um aplicativo se comunique com tags, cartões e leitores de comunicação a curta distância (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"interceptar e modificar todo o tráfego de rede"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permite que um aplicativo intercepte e inspecione todo o tráfego da rede, por exemplo, para estabelecer uma conexão VPN. Aplicativos maliciosos podem monitorar, redirecionar ou modificar pacotes de rede sem seu conhecimento."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permite que um aplicativo intercepte e inspecione todo o tráfego da rede para estabelecer uma conexão VPN. Aplicativos maliciosos podem monitorar, redirecionar ou modificar pacotes de rede sem seu conhecimento."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"desativar o bloqueio de teclas"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que um aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Um exemplo legítimo disso é a desativação do bloqueio de teclas pelo telefone ao receber uma chamada e a reativação do bloqueio quando a chamada é finalizada."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite que um aplicativo leia e grave no sistema de arquivos de cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"fazer/receber chamadas pela internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permite que um aplicativo use o serviço SIP para fazer/receber chamadas pela internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Controlar a frequência com que a senha da tela de bloqueio deve ser alterada"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Definir criptografia de armazenamento"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Exigir que os dados do aplicativo armazenado sejam criptografados"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Residencial"</item>
<item msgid="869923650527136615">"Celular"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Comercial"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Outros"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Digite o código PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Digite o PUK e o novo código PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Novo código PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Toque para inserir sua senha"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Digite a senha para desbloquear"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Digite o PIN para desbloquear"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Não há um cartão SIM no telefone."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Insira um cartão SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Apenas chamadas de emergência"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado pelo PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Se você ativar o armazenamento USB, alguns aplicativos que estão em uso serão interrompidos e poderão não estar disponíveis até você desativar o armazenamento USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Falha de operação de USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar armaz. USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar cartão SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatar o armazenamento USB, apagando todos os arquivos armazenados? A ação não pode ser revertida!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocolo de encapsulamento de camada 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec com base em chave pré-compartilhada"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec com base em certificado"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
<string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Armazenamento interno"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Cartão SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Editar..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificado de segurança"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Este certificado é válido."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emitido para:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nome comum:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organização:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unidade organizacional:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Emitido por:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validade:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Emitido em:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Expira em:"</string>
</resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 60f6049..c6fea8e 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -46,6 +46,8 @@
<string name="badPuk" msgid="5702522162746042460">"Il PUK che Vus avais tippà è nuncorrect."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Ils codes PIN che Vus avais endatà n\'èn betg identics."</string>
<string name="invalidPin" msgid="3850018445187475377">"Endatai in code PIN che cuntegna 4 fin 8 cifras."</string>
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"Vossa carta SIM è bloccada cun in PUK. Endatai il PUK per debloccar ella."</string>
<string name="needPuk2" msgid="4526033371987193070">"Endatai il PUK2 per debloccar la carta SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Numer dal telefonader (entrant)"</string>
@@ -154,7 +156,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modus d\'aviun"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Il modus d\'aviun è activà"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Il modus d\'aviun è deactivà."</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+ <!-- no translation found for status_bar_notification_info_overflow (5301981741705354993) -->
<skip />
<string name="safeMode" msgid="2788228061547930246">"Modus segirà"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
@@ -194,6 +196,10 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permetta a l\'applicaziun da retschaiver ed elavurar SMS. Applicaziuns donnegiusas pon uschia survegliar Voss messadis u als stizzar avant ch\'els vegnan mussads."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"retschaiver MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permetta a l\'applicaziun da retschaiver ed elavurar MMS. Applicaziuns donnegiusas pon uschia survegliar Voss messadis u als stizzar avant ch\'els vegnan mussads."</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<string name="permlab_sendSms" msgid="5600830612147671529">"trametter messadis SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permetta ad applicaziuns da trametter messadis SMS. Applicaziuns donnegiusas pon chaschunar custs cun trametter messadis senza As dumandar."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"leger SMS u MMS"</string>
@@ -226,6 +232,10 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permetta ad ina applicaziun da serrar tut las activitads che vegnan exequidas en il fund davant e da las spustar en il fund davos. Betg previs per applicaziuns normalas."</string>
<string name="permlab_dump" msgid="1681799862438954752">"verifitgar il status intern dal sistem"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"\"Permetta ad ina applicaziun da vesair il status intern dal sistem. Applicaziuns donnegiusas pon uschia obtegnair numerusas infurmaziuns privatas u segiradas, a las qualas ellas na dastgassan normalmain mai acceder.\""</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"serrar parzialmain"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Metta l\'administratur dad activitads en in stadi da pausa. El na vegn betg serrà dal tut."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar il midar tranter applicaziuns"</string>
@@ -326,6 +336,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"scriver datas da contact"</string>
<!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permetta ad ina applicaziun da modifitgar tut las datas da contact (adressas) memorisadas sin Voss telefonin. Applicaziuns donnegiusas pon utilisar questa funcziun per stizzar u modifitgar Vossas datas da contact."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permetta ad ina applicaziun da modifitgar tut las datas da contact (adressas) memorisadas sin Voss telefonin. Applicaziuns donnegiusas pon utilisar questa funcziun per stizzar u modifitgar Vossas datas da contact."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"leger eveniments da chalender"</string>
<!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permetta ad ina applicaziun da leger tut ils eveniments da chalender memorisads sin Voss telefonin. Applicaziuns donnegiusas pon uschia trametter Voss eveniments da chalender ad autras persunas."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permetta ad ina applicaziun da leger tut ils eveniments da chalender memorisads sin Voss telefonin. Applicaziuns donnegiusas pon uschia trametter Voss eveniments da chalender ad autras persunas."</string>
@@ -470,7 +488,7 @@
<skip />
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"deactivar la bloccaziun da la tastatura"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permetta ad ina applicaziun da deactivar la bloccaziun da la tastatura e la protecziun cun il pled-clav associada. In exempel dad ina utilisaziun legitima: La bloccaziun da la tastatura vegn deactivada sche Vus retschavais in clom ed ella vegn reactivada sche Vus finis il telefon."</string>
@@ -502,6 +520,14 @@
<skip />
<!-- no translation found for permdesc_use_sip (6320376185606661843) -->
<skip />
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<!-- outdated translation 4307861496302850201 --> <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitar il pled-clav"</string>
<!-- outdated translation 1719877245692318299 --> <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restrenscher ils tips da pleds-clav che Vus pudais utilisar."</string>
<!-- outdated translation 7374780712664285321 --> <string name="policylab_watchLogin" msgid="914130646942199503">"Survegliar las emprovas da s\'annunziar"</string>
@@ -524,6 +550,10 @@
<skip />
<!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
<skip />
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Privat"</item>
<item msgid="869923650527136615">"Telefonin"</item>
@@ -658,6 +688,12 @@
<!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
<skip />
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Endatar il code PIN"</string>
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
+ <skip />
<!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
<skip />
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Endatai il pled-clav per debloccar."</string>
@@ -683,6 +719,10 @@
<!-- outdated translation 2186920585695169078 --> <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"En il telefon na sa chatta nagina carta SIM."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"En il telefon na sa chatta nagina carta SIM."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Inseri per plaschair ina carta SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Mo cloms d\'urgenza"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rait bloccada"</string>
<!-- no translation found for lockscreen_sim_puk_locked_message (7441797339976230) -->
@@ -989,6 +1029,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Sche Vus activais l\'apparat periferic da memoria USB sa ferman tschertas applicaziuns che Vus utilisais. Ellas n\'èn probablamain betg disponiblas enfin che l\'apparat periferic vegn puspè deactivà."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operaziun USB betg reussida"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar la carta SD"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatar la carta SD"</string>
<!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vulais Vus propi formatar la carta SD? En quest cas van tut las datas sin Vossa carta a perder."</string>
@@ -1058,6 +1102,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol Layer 2 Tunneling"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basà sin ina clav precundividida"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basà sin in certificat"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Tscherner ina datoteca"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nagina datoteca tschernida"</string>
<string name="reset" msgid="2448168080964209908">"Reinizialisar"</string>
@@ -1159,4 +1211,26 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificat da segirezza"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Quest certificat è valid."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emess a:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Num general:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisaziun:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unitad d\'organisaziun:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Emess da:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validitad:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Emess ils:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Scroda ils:"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 1961903..25fdb54 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Codul PUK introdus nu este corect."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Codurile PIN introduse nu se potrivesc."</string>
<string name="invalidPin" msgid="3850018445187475377">"Introduceţi un cod PIN alcătuit din 4 până la 8 cifre."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Introduceţi un cod PUK care să aibă 8 cifre sau mai mult."</string>
<string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
<string name="needPuk2" msgid="4526033371987193070">"Introduceţi codul PUK2 pentru a debloca cardul SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID apelant de primire"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modul Avion este ACTIVAT"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modul avion este DEZACTIVAT"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Permite aplicaţiilor să primească şi să proceseze mesaje SMS. Aplicaţiile rău-intenţionate ar putea să monitorizeze mesajele sau să le şteargă fără să vi le arate."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"primire MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Permite aplicaţiei să primească şi să proceseze mesaje MMS. Aplicaţiile rău-intenţionate ar putea să monitorizeze mesajele sau să le şteargă fără să vi le arate."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"primeşte mesaje difuzate de urgenţă"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Permite aplicaţiei să primească şi să proceseze mesajele difuzate de urgenţă. Această permisiune este disponibil numai pentru aplicaţiile sistemului."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"trimitere mesaje SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Permite aplicaţiei să trimită mesaje SMS. Aplicaţiile rău-intenţionate ar putea să vă genereze costuri, deoarece trimit mesaje fără confirmarea dvs."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"citire mesaje SMS sau MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Permite unei aplicaţii să forţeze închiderea şi trimiterea în fundal a oricărei activităţi care rulează în prim-plan. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_dump" msgid="1681799862438954752">"regăsire stare internă a sistemului"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Permite unei aplicaţii să regăsească starea internă a sistemului. Aplicaţiile rău-intenţionate ar putea să regăsească o gamă variată de informaţii confidenţiale şi securizate, de care în mod normal nu ar avea nevoie niciodată."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"preia conţinutul de pe ecran"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Permite aplicaţiei să preia conţinutul ferestrei active. Aplicaţiile rău intenţionate pot să preia întregul conţinut al ferestrei şi să examineze tot textul acesteia, cu excepţia parolelor."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"închidere parţială"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Plasează Managerul de activităţi într-o stare de închidere. Nu efectuează o închidere completă."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Permite proprietarului să trimită intenţii către un administrator al dispozitivului. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"modificare orientare ecran"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Permite unei aplicaţii să modifice rotaţia ecranului în orice moment. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"modifică viteza indicatorului"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Permite unei aplicaţii să modifice oricând viteza indicatorului mouse-ului sau a trackpadului. Nu ar trebui să fie necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"trimitere semnale Linux către aplicaţii"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Permite aplicaţiei să solicite trimiterea semnalului furnizat către toate procesele persistente."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"rulare întotdeauna a aplicaţiei"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"scriere date de contact"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"citire evenimente din calendar"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlare schimb de date prin Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Permite unei aplicaţii să comunice cu etichetele, cardurile şi cititoarele NFC (Near Field Communication)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"interceptează şi modifică tot traficul de reţea"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Permite unei aplicaţii să intercepteze şi să inspecteze tot traficul de reţea, de exemplu, pentru a stabili o conexiune VPN. Aplicaţiile rău intenţionate pot monitoriza, redirecţiona sau modifica pachetele de reţea fără ştirea dvs."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Permite unei aplicaţii să intercepteze şi să inspecteze tot traficul de reţea pentru a stabili o conexiune VPN. Aplicaţiile rău intenţionate pot monitoriza, redirecţiona sau modifica pachetele de reţea fără ştirea dvs."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"dezactivare blocare taste"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite unei aplicaţii să dezactiveze blocarea tastelor şi orice modalitate asociată de securitate a parolelor. Un bun exemplu este deblocarea tastelor de către telefon atunci când se primeşte un apel şi reactivarea blocării tastelor la terminarea apelului."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"citire setări sincronizare"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite unei aplicaţii să scrie şi să citească sistemul de fişiere cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"efectuare/primire apeluri prin internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Permite unei aplicaţii să utilizeze serviciul SIP pentru a efectua/primi apeluri prin internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlarea lungimii şi a tipului de caractere permise în parolele pentru deblocarea ecranului."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Stabiliţi frecvenţa de schimbare a parolei de blocare a ecranului"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setaţi criptarea stocării"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Necesită ca datele aplicaţiei stocate să fie criptate"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Domiciliu"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Serviciu"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altul"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduceţi codul PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Introduceţi codul PUK şi noul cod PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codul PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Noul cod PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Ating. şi intr. parola"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduceţi parola pentru a debloca"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introduceţi PIN pentru deblocare"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Introduceţi un card SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Numai apeluri de urgenţă"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Reţea blocată"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Cardul SIM este blocat cu codul PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Dacă activaţi stocarea USB, unele aplicaţii pe care le utilizaţi în prezent se vor opri şi ar putea să nu fie disponibile până când dezactivaţi stocarea USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operaţie USB nereuşită"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formataţi stoc. USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formataţi cardul SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formataţi stocarea USB, ştergând toate fişierele stocate aici? Acţiunea nu poate fi anulată!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protocol de tunel Nivel 2 (L2TP)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec bazat pe cheie prepartajată"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec bazat pe certificat"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fişiere"</string>
<string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Stocare internă"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Card SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Dsipozitiv de stocare USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Editaţi..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificat de securitate"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Certificatul este valid."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emis de:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nume comun:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizaţie:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizaţie:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Emis de:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validitate:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Emis pe:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Expiră pe:"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 83dc30f..170ee85 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Введен неверный PUK."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Введенные PIN-коды не совпадают."</string>
<string name="invalidPin" msgid="3850018445187475377">"Введите PIN-код (от 4 до 8 цифр)."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Введите PUK-код из 8 или более цифр."</string>
<string name="needPuk" msgid="919668385956251611">"SIM-карта заблокирована с помощью кода PUK. Для разблокировки введите код PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Для разблокировки SIM-карты введите PUK2."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Идентификация вызывающего абонента"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим полета"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим полета ВКЛЮЧЕН"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим полета ВЫКЛЮЧЕН"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Платные услуги"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Позволяет приложению получать и обрабатывать SMS-сообщения. Вредоносные приложения могут отслеживать ваши сообщения или удалять их, не показывая вам."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"получать MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Позволяет приложению получать и обрабатывать MMS-сообщения. Вредоносные приложения могут отслеживать ваши сообщения или удалять их, не показывая вам."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"принимать экстренные вызовы"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Позволяет приложению принимать и обрабатывать экстренные сообщения. Это разрешение доступно только для системных приложений."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"отправлять SMS-сообщения"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Позволяет приложению отправлять SMS-сообщения. Вредоносные приложения могут отправлять сообщения без уведомления, что приведет к непредвиденным расходам."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"считывать SMS или MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Позволяет приложению принудительно закрыть или вернуть в исходное состояние процессы, выполняемые в активном режиме. Не требуется для обычных приложений."</string>
<string name="permlab_dump" msgid="1681799862438954752">"извлекать данные о внутреннем состоянии системы"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Позволяет приложению извлекать внутренние сведения о состоянии системы. Вредоносные приложения смогут извлечь разнообразные личные и защищенные сведения, в которых обычно нет необходимости."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"получать доступ к содержанию экрана"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Позволяет приложению получать доступ к содержанию активного окна. Вредоносное ПО может извлечь все данные окна и проанализировать весь его текст, кроме паролей."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"частичное завершение работы"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запретить переключение приложений"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Позволяет владельцу отправлять целевые значения администратору устройства. Никогда не используется обычными приложениями."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"изменять ориентацию экрана"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Позволяет приложению изменять ориентацию экрана в любое время. Не требуется для обычных приложений."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"изменять скорость указателя"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Позволяет приложению изменять скорость указателя мыши или трекпада. Для большинства приложений это не требуется."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"отправлять приложениям сигналы Linux"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Позволяет приложению направлять запрос на передачу предоставленного сигнала всем постоянным процессам."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"запускать постоянную работу приложения"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"перезаписывать данные контакта"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Позволяет приложению изменять данные (адрес) контакта, сохраненные в памяти планшетного ПК. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных контакта."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Позволяет приложению изменять данные (адрес) контакта, сохраненные в памяти телефона. Вредоносные приложения могут использовать эту возможность для удаления или изменения данных контакта."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"считывать мероприятия в календаре"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Позволяет приложению считывать все события календаря, сохраненные на планшетном ПК. Вредоносные приложения могут использовать эту возможность для передачи ваших событий календаря посторонним лицам."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Позволяет приложению считывать все события календаря, сохраненные на телефоне. Вредоносные приложения могут использовать эту возможность для передачи ваших событий календаря посторонним лицам."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"управлять радиосвязью ближнего действия"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Позволяет приложению обмениваться данными с метками, картами и считывателями через радиосвязь ближнего действия (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"перехватывать и изменять сетевой трафик"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Позволяет приложению перехватывать и проверять весь сетевой трафик, например чтобы установить соединение VPN. Вредоносное ПО может отслеживать, перенаправлять или изменять сетевые пакеты без вашего ведома."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Позволяет приложению перехватывать и проверять весь сетевой трафик для установки соединения VPN. Вредоносное ПО может отслеживать, перенаправлять или изменять сетевые пакеты без вашего ведома."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"отключать блокировку клавиатуры"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Позволяет приложению отключить блокировку клавиатуры и другие функции защиты паролем. Примером допустимого использования этой функции является отключение блокировки клавиатуры при получении входящего вызова и включение блокировки после завершения разговора."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"считывать настройки синхронизации"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешает программам доступ для записи и чтения к кэшу файловой системы."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"совершать и принимать интернет-вызовы"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Позволяет приложению использовать службу SIP для интернет-вызовов."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Укажите, как часто следует менять пароль блокировки экрана"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Настроить шифрование хранилища"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Требует шифровать данные приложений, находящиеся в хранилище."</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Домашний"</item>
<item msgid="869923650527136615">"Мобильный"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Рабочий"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Другой"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Введите PIN-код"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Введите PUK-код и новый PIN-код"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-код"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Новый PIN-код"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Нажмите для ввода пароля"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Введите пароль для разблокировки"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Введите PIN-код для разблокировки"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"SIM-карта не установлена."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"SIM-карта не установлена."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Вставьте SIM-карту."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"При включении USB-накопителя некоторые используемые приложения могут прекратить работу и оставаться недоступными до отключения USB-накопителя."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Сбой операции USB-подключения"</string>
<string name="dlg_ok" msgid="7376953167039865701">"ОК"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматирование USB-накопителя безвозвратно удалит все файлы на нем! Продолжить?"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Протокол L2TP"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN с использованием общего ключа"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN с использованием сертификатов"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
<string name="reset" msgid="2448168080964209908">"Сбросить"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Внутренняя память"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-карта"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-накопитель"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Изменить..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Сертификат безопасности"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Этот сертификат действителен."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Владелец сертификата:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Стандартное имя:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Организация:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Подразделение организации:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Выпущен:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Срок действия:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Дата издания:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Дата окончания действия:"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3439f59..4ef89b7 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Kód PUK bol zadaný nesprávne."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Zadané kódy PIN sa nezhodujú."</string>
<string name="invalidPin" msgid="3850018445187475377">"Zadajte kód PIN s dĺžkou 4 až 8 číslic."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Zadajte kód PUK, ktorý má 8 alebo viac čísel."</string>
<string name="needPuk" msgid="919668385956251611">"Karta SIM je uzamknutá pomocou kódu PUK. Odomknite ju zadaním kódu PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ak chcete odblokovať kartu SIM, zadajte kód PUK2."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Prichádzajúca identifikácia volajúceho"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V lietadle"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V lietadle je ZAPNUTÝ"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V lietadle je VYPNUTÝ"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Spoplatnené služby"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Umožňuje aplikácii prijímať a spracovávať správy SMS. Škodlivé aplikácie môžu sledovať vaše správy alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"príjem správ MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Škodlivé aplikácie môžu sledovať vaše správy alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"príjem núdzového vysielania"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Umožňuje aplikácii prijímať a spracúvať správy núdzového vysielania. Toto oprávnenie je k dispozícii iba pre systémové aplikácie."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"odosielať správy SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Umožňuje aplikácii odosielať správy SMS. Škodlivé aplikácie môžu bez vášho potvrdenia odosielať spoplatnené správy."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"čítanie správ SMS a MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Umožňuje aplikácii vynútiť zavretie ľubovoľnej činnosti v popredí a jej presunutie do pozadia. Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
<string name="permlab_dump" msgid="1681799862438954752">"načítanie interného stavu systému"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Umožňuje aplikácii načítať interný stav systému. Škodlivé aplikácie môžu načítať široký rozsah súkromných a zabezpečených informácií, ktoré by obvykle nemali nikdy využívať."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"načítanie obsahu obrazovky"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu načítať celý obsah okna okrem hesiel a preskúmať ho."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto oprávnenie nemali nikdy požadovať."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"zmena orientácie obrazovky"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Umožňuje aplikácii kedykoľvek zmeniť orientáciu obrazovky. Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmena rýchlosti ukazovateľa"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Umožňuje aplikácii kedykoľvek zmeniť rýchlosť ukazovateľa myši alebo trackpadu. Bežné aplikácie by toto oprávnenie nemali nikdy požadovať."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"odoslanie signálov systému Linux aplikáciám"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Umožňuje aplikácii vyžiadať zaslanie poskytnutého signálu všetkým trvalým procesom."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"trvalé spustenie aplikácie"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"zápis údajov kontaktov"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Umožňuje aplikácii zmeniť kontaktné údaje (adresu) uložené v tablete. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť kontaktné údaje."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Umožňuje aplikácii zmeniť kontaktné údaje (adresu) uložené v telefóne. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť kontaktné údaje."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"čítanie udalostí v kalendári"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Umožňuje aplikácii načítať všetky udalosti kalendára uložené vo vašom tablete. Škodlivé aplikácie potom môžu ďalším ľuďom odoslať udalosti z vášho kalendára."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Umožňuje aplikácii načítať všetky udalosti kalendára uložené vo vašom telefóne. Škodlivé aplikácie potom môžu ďalším ľuďom odoslať udalosti z vášho kalendára."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Umožňuje aplikácii komunikovať so štítkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"zachytiť a upraviť celú sieťovú aktivitu"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Umožňuje aplikácii zachytiť a skontrolovať celú sieťovú aktivitu, napríklad za účelom nadviazania spojenia VPN. Škodlivé aplikácie môžu sledovať, presmerovať alebo meniť sieťové pakety bez vášho vedomia."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Umožňuje aplikácii zachytiť a skontrolovať všetku návštevnosť siete s cieľom nadviazať spojenie so sieťou VPN. Škodlivé aplikácie môžu sledovať, presmerovať alebo upravovať sieťové pakety bez vášho vedomia."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"zakázanie uzamknutia klávesnice"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikácii vypnúť uzamknutie klávesnice a súvisiace zabezpečenie heslom. Príkladom oprávneného použitia tejto funkcie je vypnutie uzamknutia klávesnice pri prichádzajúcom hovore a jej opätovné zapnutie po skončení hovoru."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"uskutočňovať a prijímať internetové hovory"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikácii uskutočniť a prijímať internetové hovory pomocou služby SIP."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Ovládať dĺžku hesiel pre odomknutie obrazovky a v nich používané znaky"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Nastavte, ako často sa musí zmeniť heslo na uzamknutie obrazovky"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastaviť šifr. ukl. priestoru"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Vyžaduje šifrovanie uložených údajov aplikácií"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Domovská stránka"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Práca"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Iné"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Zadajte kód PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Zadajte kód PUK a nový kód PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kód PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nový kód PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Po dotyku môžete zadať heslo"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Zadajte heslo pre odomknutie"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Zadajte kód PIN pre odomknutie"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tablete nie je žiadna karta SIM."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefóne nie je žiadna karta SIM."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vložte kartu SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Len tiesňové volania"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Sieť je zablokovaná"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Karta SIM je uzamknutá pomocou kódu PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ak zapnete ukladací priestor USB, dôjde k zastaveniu niektorých používaných aplikácií. Tieto aplikácie pravdepodobne nebudú k dispozícii až do vypnutia ukladacieho priestoru USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Chyba operácie na rozhraní USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formát. ukl. priestor USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovať kartu SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete ukladací priestor USB naformátovať a vymazať tak všetky súbory, ktoré sú v ňom uložené? Túto akciu nie je možné vrátiť späť."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Protokol L2TP (Layer 2 Tunneling Protocol)"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Sieť VPN L2TP/IPSec s vopred zdieľaným kľúčom"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sieť VPN L2TP/IPSec s certifikátom"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string>
<string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Interný ukladací priestor"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Karta SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Ukladací priestor USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Upraviť..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certifikát zabezpečenia"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Certifikát je platný."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Vydané pre:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Bežný názov:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizácia:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizačná jednotka:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Vydal:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Platnosť:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Dátum vydania:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Platnosť vyprší:"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index cd4cd07..86546e02 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Vneseni PUK ni pravilen."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Vneseni številki PIN se ne ujemata."</string>
<string name="invalidPin" msgid="3850018445187475377">"Vnesite PIN, ki vsebuje od štiri do osem številk."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Vnesite 8- ali več mestni PUK."</string>
<string name="needPuk" msgid="919668385956251611">"Kartica SIM je zaklenjena s kodo PUK. Če jo želite odkleniti, vnesite kodo PUK."</string>
<string name="needPuk2" msgid="4526033371987193070">"Če želite odstraniti blokiranje kartice SIM, vnesite PUK2."</string>
<string name="ClipMmi" msgid="6952821216480289285">"ID dohodnega klicatelja"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način za letalo"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Način za letalo je VKLOPLJEN"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način za letalo je IZKLOPLJEN"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Plačljive storitve"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Programu dovoljuje prejemanje in obdelavo sporočil SMS. Zlonamerni programi lahko nadzorujejo sporočila ali jih izbrišejo, ne da bi vam jih pokazali."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"prejemanje sporočil MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Programu dovoljuje sprejem in obdelavo sporočila MMS. Zlonamerni programi lahko nadzorujejo sporočila ali jih izbrišejo, ne da bi vam jih pokazali."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"prejemanje oddaj v sili"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Dovoli programu, da sprejme in obdela sporočila oddaj v sili. To dovoljenje je na voljo samo za sistemske programe."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"pošiljanje sporočil SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Programom dovoljuje pošiljanje sporočil SMS. Zlonamerni programi lahko pošiljajo sporočila brez vaše potrditve, kar vas lahko drago stane."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"branje sporočil SMS ali MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Dovoljuje, da program vsili zaustavitev katere koli dejavnosti, ki je v ospredju, in premakne dejavnosti v ozadje. Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_dump" msgid="1681799862438954752">"pridobivanje notranjega stanja sistema"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Programu dovoljuje pridobivanje notranjega stanja sistema. Zlonamerni programi lahko pridobijo najrazličnejše osebne in varnostne informacije, ki jih navadno nikoli ne bi potrebovali."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"prenos vsebine zaslona"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Dovoli programu, da prenese vsebino iz aktivnega okna. Zlonamerni programi lahko prenesejo celotno vsebino okna in preberejo vse besedilo, razen gesel."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delna zaustavitev"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Upravitelja dejavnosti preklopi v stanje za zaustavitev. Ne izvede celotne zaustavitve."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Dovoljuje lastniku, da pošlje namere skrbniku naprave. Nikoli se ne uporablja za navadne programe."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"spreminjanje usmerjenosti zaslona"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Dovoljuje, da program kadar koli spremeni smer sukanja zaslona. Tega nikoli ni treba uporabiti za navadne programe."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"spreminjanje hitrosti kazalca"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Dovoli programu, da kadar koli spremeni hitrost kazalca miške ali sledilne ploščice. Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"pošiljanje signalov Linuxa programom"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Dovoljuje, da program zahteva, da je posredovan signal poslan vsem trajnim procesom."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"neprekinjeno izvajanje programov"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"pisanje podatkov stika"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Programu omogoča spreminjanje podatkov (naslovov), shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem izbrišejo ali spremenijo podatke o stikih."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Programu dovoljuje spreminjanje podatkov stika (naslov), shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov stika."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"branje koledarskih dogodkov"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Programu omogoča branje vseh koledarskih vnosov, shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem pošljejo vnose drugim uporabnikom."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Programu dovoljuje branje vseh dogodkov koledarja, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za pošiljanje dogodkov koledarja drugim osebam."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"prestrezanje in spreminjanje vsega omrežnega prometa"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Dovoli programu, da prestreže in pregleda ves omrežni promet, na primer za vzpostavljanje povezave VPN. Zlonamerni programi lahko brez vašega vedenja spremljajo, preusmerjajo ali spreminjajo omrežne pakete."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Dovoli programu, da prestreže in pregleda ves omrežni promet za vzpostavljanje povezave v navideznem zasebnem omrežju. Zlonamerni programi lahko brez vašega vedenja spremljajo, preusmerjajo ali spreminjajo omrežne pakete."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"onemogočanje zaklepa tipkovnice"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Dovoljuje, da program onemogoči zaklep tipk in morebitno povezano varnostno geslo. Legitimen primer je onemogočenje zaklepa tipkovnice pri dohodnem klicu ter vnovičnem omogočanju zaklepa, ko je klic dokončan."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"branje nastavitev sinhronizacije"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Programu dovoljuje branje in pisanje v datotečni sistem predpomnilnika."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"opravljanje/sprejemanje internetnih klicev"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Programu omogoča uporabo storitve SIP za opravljanje in sprejemanje internetnih klicev."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Določite, kako pogosto je treba spremeniti geslo za zaklepanje zaslona"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavitev šifriranja shrambe"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Shranjeni podatki programa morajo biti šifrirani"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Začetna stran"</item>
<item msgid="869923650527136615">"Mobilni"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Služba"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Vnesite kodo PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Vnesite kodo PUK in novo kodo PIN"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Koda PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Nova koda PIN"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Dotaknite se za vnos gesla"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Vnesite geslo za odklop"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Vnesite PIN za odklepanje"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabličnem računalniku ni kartice SIM."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"V telefonu ni kartice SIM."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vstavite kartico SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Le klici v sili"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Omrežje je zaklenjeno"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kartica SIM je zaklenjena s kodo PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Če vklopite shrambo USB, bodo nekateri programi, ki jih uporabljate, ustavljeni in morda ne bodo na voljo, dokler je ne izklopite."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Operacija USB ni uspela"</string>
<string name="dlg_ok" msgid="7376953167039865701">"V redu"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiranje pomnilnika USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj kartico SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ali želite formatirati pomnilnik USB in izbrisati vse datoteke, shranjene na njem? Dejanje je dokončno."</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Tunelski protokol L2TP"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN, ki temelji na ključu v vnaprejšnji skupni rabi"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN, ki temelji na potrdilu"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
<string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Notranji pomnilnik"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Kartica SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Pomnilnik USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Urejanje ..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Varnostno potrdilo"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Potrdilo je veljavno."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Izdano za:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Pogosto ime:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organizacija:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organizacijska enota:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Izdal:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Veljavnost:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Izdano:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Velja do:"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 59329b4..2fd051c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK који сте унели није тачан."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN кодови које сте унели се не подударају."</string>
<string name="invalidPin" msgid="3850018445187475377">"Откуцајте PIN који има од 4 до 8 бројева."</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="ClipMmi" msgid="6952821216480289285">"Долазећи ИД позиваоца"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим рада у авиону"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим рада у авиону је УКЉУЧЕН"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим рада у авиону је ИСКЉУЧЕН"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Омогућава да апликација прима и обрађује SMS поруке. Злонамерне апликације могу да надгледају поруке или да их бришу, а да вам их не прикажу."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"пријем MMS порука"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Омогућава да апликација прима и обрађује MMS поруке. Злонамерне апликације могу да надгледају поруке или да их бришу, а да вам их не прикажу."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"пријем хитних преноса"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Дозвољава апликацији да прима и обрађује поруке хитног преноса. Ова дозвола је доступна само за системске апликације."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"слање SMS порука"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Омогућава да апликација шаље SMS поруке. Злонамерне апликације могу да шаљу поруке без ваше потврде, што ће вам створити трошкове."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"читање SMS или MMS порука"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Омогућава да апликација принудно обустави било коју активност која се одвија у првом плану. Обичне апликације никада не би требало да је користе."</string>
<string name="permlab_dump" msgid="1681799862438954752">"преузимање интерног статуса система"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Омогућава да апликација преузме интерни статус система. Злонамерне апликације могу да преузму разноврсне приватне и безбедносне информације за којима никада не би требало да имају потребе."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"преузимање садржаја екрана"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Дозвољава апликацији да преузме садржај активног прозора. Злонамерне апликације могу да преузму читав садржај прозора и прегледају целокупан текст осим лозинки."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Омогућава власнику да шаље своје намере администратору уређаја. Обичне апликације никада не би требало да је користе."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"промена положаја екрана"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Омогућава да апликација у сваком тренутку промени ротацију екрана. Обичне апликације никада не би требало да је користе."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"промена брзине показивача"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Дозвољава апликацији да у било ком тренутку промени брзину показивача миша или показивачког уређаја са плочицом. Никада не би требало да буде потребно за обичне апликације."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"слање Linux сигнала апликацијама"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Омогућава да апликација захтева да испоручени сигнал буде послат свим трајним процесима."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"омогућавање непрекидне активности апликације"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"уписивање података о контактима"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Омогућава апликацији да измени податке о контакту (адресу) сачуване на таблету. Злонамерне апликације на тај начин могу да избришу или измене податке о контакту."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Омогућава да апликација измени податке о контакту (адреси) сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке о контакту."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"читање догађаја из календара"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Омогућава апликацији да чита све догађаје из календара сачуване на таблету. Злонамерне апликације то могу да злоупотребе и пошаљу ваше догађаје из календара другим особама."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Омогућава да апликација чита све догађаје из календара сачуване на телефону. Злонамерне апликације могу то да злоупотребе и искористе за слање догађаја из календара другим људима."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"контрола комуникације у ужем пољу (Near Field Communication)"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Омогућава апликацији да комуницира са ознакама, картицама и читачима комуникације у ужем пољу (Near Field Communication – NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"пресретање и измена целокупног мрежног саобраћаја"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Омогућава апликацији да пресреће и прегледа сав мрежни саобраћај, на пример, да би успоставила VPN везу. Злонамерне апликације могу да прате, преусмеравају или мењају мрежне пакете без вашег знања."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Омогућава апликацији да пресреће и прегледа сав мрежни саобраћај да би успоставила VPN везу. Злонамерне апликације могу да прате, преусмеравају или мењају мрежне пакете без вашег знања."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"онемогућавање закључавања тастатуре"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Омогућава да апликација онемогући закључавање тастатуре и свих безбедносних мера успостављених на основу лозинке. У оправдане примере додељивања такве дозволе спада онемогућавање закључавања тастатуре при пријему долазећег телефонског позива и поновно омогућавање тастатуре по његовом завршетку."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"читање подешавања синхронизације"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Омогућава да апликација чита систем датотека кеша и уписује податке у њега."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"упућивање/пријем Интернет позива"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Омогућава апликацији да користи SIP услугу за упућивање/пријем Интернет позива."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Контрола дужине и знакова дозвољених у лозинкама за откључавање лозинки"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролишите колико често лозинка за закључавање екрана мора да се мења"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Подешавање шифровања складишта"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Захтева да сачувани подаци апликације буду шифровани"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Кућа"</item>
<item msgid="869923650527136615">"Мобилни"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Посао"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Други"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Унесите PIN кôд"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Унесите PUK и нови PIN кôд"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK кôд"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Нови PIN кôд"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Додирните за унос лозинке"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Унесите лозинку за откључавање"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Унесите PIN да бисте откључали тастатуру"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У телефон није уметнута SIM картица."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Уметните SIM картицу."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако укључите USB складиште, поједине апликације које користите престаће да раде и могу да постану недоступне док га поново не укључите."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Грешка са USB складиштем"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Потврди"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Желите да форматирате USB меморију и избришете све датотеке у њој? Ову радњу није могуће опозвати!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Протокол тунеловања слоја 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Унапред дељени кључ заснован на протоколу L2TP/IPSec за VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Сертификат заснован на протоколу L2TP/IPSec за VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
<string name="reset" msgid="2448168080964209908">"Поново постави"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Интерна меморија"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD картица"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB меморија"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Измени..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Безбедносни сертификат"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Овај сертификат је важећи."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Издато за:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Уобичајени назив:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Организација:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Организациона јединица:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Издавалац:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Ваљаност:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Издато дана:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Датум истека:"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index a3350e5..a17dc8d 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK-koden som du angav är fel."</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN-koderna som du angav matchar inte."</string>
<string name="invalidPin" msgid="3850018445187475377">"Ange en PIN-kod som är 4 till 8 siffror."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Ange en PUK-kod med minst 8 siffror."</string>
<string name="needPuk" msgid="919668385956251611">"Ditt SIM-kort är PUK-låst. Ange PUK-koden om du vill låsa upp det."</string>
<string name="needPuk2" msgid="4526033371987193070">"Ange PUK2-koden för att häva spärren av SIM-kortet."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Nummerpresentatör för inkommande samtal"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flygplansläge"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flygplansläge är AKTIVERAT"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flygplansläge är INAKTIVERAT"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">">100"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">100"</string>
<string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjänster som kostar pengar"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Tillåter att program tar emot och bearbetar SMS-meddelanden. Skadliga program kan övervaka dina meddelanden eller ta bort dem utan att visa dem för dig."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"ta emot MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Tillåter att program tar emot och bearbetar MMS-meddelanden. Skadliga program kan övervaka dina meddelanden eller ta bort dem innan du har sett dem."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"ta emot sändningar i nödsituationer"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Tillåter att appen tar emot och bearbetar sändningar i nödsituationer. Behörigheten är bara tillgänglig för systemappar."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"skicka SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Tillåter att programmet skickar SMS-meddelanden. Skadliga program kan skicka meddelanden utan ditt godkännande vilket kan kosta pengar."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"läsa SMS eller MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Tillåter att ett program tvingar en aktivitet som finns i förgrunden att avsluta och gå tillbaka. Behövs inte för vanliga program."</string>
<string name="permlab_dump" msgid="1681799862438954752">"hämta systemets interna status"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Tillåter att ett program hämtar systemets interna status. Skadliga program kan hämta privat och skyddad information som de normalt aldrig ska behöva."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hämta skärminnehåll"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Tillåter att appar hämtar innehållet i det aktiva fönstret. Skadliga appar kan hämta hela fönsterinnehållet och läsa all text utom lösenord."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"avsluta delvis"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Sätter aktivitetshanteraren i avstängningsläge. Utför inte en fullständig avstängning."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga program behöver aldrig göra detta."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ändra bildskärmens rikting"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Tillåter att ett program när som helst ändrar skärmens rotering. Behövs inte för vanliga program."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ändra markörens hastighet"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Tillåter att en app när som helst ändrar hastigheten för musens eller styrplattans markör. Ska inte behövas för vanliga appar."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"skicka Linux-signaler till appar"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Tillåter att programmet begär att den angivna signalen skickas till alla beständiga processer."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"se till att programmet alltid körs"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"skriva kontaktuppgifter"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Tillåter att ett program ändrar kontaktuppgifter (adresser) som har lagrats på pekdatorn. Skadliga program kan använda detta för att radera eller ändra kontaktuppgifter."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Tillåter att ett program ändrar kontaktuppgifter (adress) som har lagrats på din telefon. Skadliga program kan använda detta för att radera eller ändra kontaktuppgifter."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"läsa kalenderhändelser"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Tillåter att ett program läser alla händelser i kalendern som har lagrats på pekdatorn. Skadliga program kan använda detta för att skicka dina kalenderuppgifter till andra personer."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Tillåter att ett program läser alla händelser i kalendern som har lagrats på din telefon. Skadliga program kan använda detta för att skicka din kalender till andra personer."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontrollera närfältskommunikationen"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Tillåter att en app kommunicerar med taggar, kort och läsare för närfältskommunikation (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"fånga upp och ändra all nätverkstrafik"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Tillåter en app att fånga upp och inspektera all nätverkstrafik, till exempel för att upprätta en VPN-anslutning. Skadliga appar kan övervaka, omdirigera och ändra nätverkspaket utan att du märker det."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Tillåter att en app fångar upp och inspekterar all nätverkstrafik för att upprätta en VPN-anslutning. Skadliga appar kan övervaka, omdirigera och ändra nätverkspaket utan att du märker det."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"inaktivera tangentlås"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillåter att ett program inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel på detta är att telefonen inaktiverar tangentlåset vid inkommande samtal och sedan aktiverar det igen när samtalet är avslutat."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Tillåter att ett program läser och skriver till cachefilsystemet."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"ringa/ta emot Internetsamtal"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Tillåter att appen använder SIP-tjänsten för att ringa och ta emot Internetsamtal."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Styr hur ofta lösenordet till skärmlåset måste ändras"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ange krypterad lagring"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Kräv att sparade applikationsdata krypteras."</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Hem"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbete"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Övrigt"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ange PIN-kod"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Ange PUK-koden och en ny PIN-kod"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kod"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Ny PIN-kod"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Tryck om du vill ange lösenord"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ange lösenord för att låsa upp"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ange PIN-kod för att låsa upp"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Inget SIM-kort i pekdatorn."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Inget SIM-kort i telefonen."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Sätt i ett SIM-kort."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Endast nödsamtal"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Nätverk låst"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM-kortet är PUK-låst."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Om du aktiverar USB-lagring avbryts några av de appar som körs och de kanske inte blir tillgängliga igen förrän du inaktiverar USB-lagring."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB-åtgärd misslyckades"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatera USB-enhet"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatera SD-kort"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatera SD-kort och radera alla filer? Åtgärden kan inte ångras!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"I förväg delad L2TP/IPSec VPN-nyckel"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Certifikatsbaserad L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Välj fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil har valts"</string>
<string name="reset" msgid="2448168080964209908">"Återställ"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Internt lagringsutrymme"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD-kort"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB-lagring"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Redigera..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Säkerhetscertifikat"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Detta certifikat är giltigt."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Utfärdat till:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Nätverksnamn:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisation:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Organisationsenhet:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Utfärdat av:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Giltighet:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Utfärdat den:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Upphör att gälla:"</string>
</resources>
diff --git a/core/res/res/values-sw-rTZ/arrays.xml b/core/res/res/values-sw-rTZ/arrays.xml
new file mode 100644
index 0000000..d1018a7
--- /dev/null
+++ b/core/res/res/values-sw-rTZ/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>-6369028</item>
+ <item>34888822</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index ff1907a..27109c8 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -70,6 +70,8 @@
<skip />
<!-- no translation found for invalidPin (3850018445187475377) -->
<skip />
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"Kadi yako ya SIM imefungwa na PUK. Anika msimbo wa PUK ili kuifungua."</string>
<!-- no translation found for needPuk2 (4526033371987193070) -->
<skip />
@@ -189,16 +191,12 @@
<!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
<skip />
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Ufutaji mwingi sana <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
- <!-- no translation found for low_memory (2292820184396262278) -->
- <skip />
- <!-- no translation found for low_memory (6632412458436461203) -->
- <skip />
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Hifadhi ya kompyuta ndogo imejaa! Futa baadhi ya faili ili uweze kupata nafasi."</string>
+ <!-- outdated translation 2292820184396262278 --> <string name="low_memory" product="default" msgid="6632412458436461203">"Hifadhi ya kompyuta ndogo imejaa! Futa baadhi ya faili ili uweze kupata nafasi."</string>
<!-- no translation found for me (6545696007631404292) -->
<skip />
- <!-- no translation found for power_dialog (8545351420865202853) -->
- <skip />
- <!-- no translation found for power_dialog (1319919075463988638) -->
- <skip />
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Chaguo za kompyuta ndogo"</string>
+ <!-- outdated translation 8545351420865202853 --> <string name="power_dialog" product="default" msgid="1319919075463988638">"Chaguo za kompyuta ndogo"</string>
<!-- no translation found for silent_mode (7167703389802618663) -->
<skip />
<!-- no translation found for turn_on_radio (3912793092339962371) -->
@@ -211,19 +209,14 @@
<skip />
<!-- no translation found for shutdown_progress (2281079257329981203) -->
<skip />
- <!-- no translation found for shutdown_confirm (3385745179555731470) -->
- <skip />
- <!-- no translation found for shutdown_confirm (649792175242821353) -->
- <skip />
- <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
- <skip />
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Kompyuta yako ndogo itazima."</string>
+ <!-- outdated translation 3385745179555731470 --> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Kompyuta yako ndogo itazima."</string>
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"Je, ungependa kuzima?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Za hivi karibuni"</string>
<!-- no translation found for no_recent_tasks (279702952298056674) -->
<skip />
- <!-- no translation found for global_actions (408477140088053665) -->
- <skip />
- <!-- no translation found for global_actions (2406416831541615258) -->
- <skip />
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Chaguo za kompyuta ndogo"</string>
+ <!-- outdated translation 408477140088053665 --> <string name="global_actions" product="default" msgid="2406416831541615258">"Chaguo za kompyuta ndogo"</string>
<!-- no translation found for global_action_lock (2844945191792119712) -->
<skip />
<!-- no translation found for global_action_power_off (4471879440839879722) -->
@@ -237,8 +230,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"gumzo ya ndege"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Hali ya ndege IMEWASHWA"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"gumzo ya ndege IMEZIMWA"</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
- <skip />
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<!-- no translation found for safeMode (2788228061547930246) -->
<skip />
<string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
@@ -250,7 +242,7 @@
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Soma na andika SMS yako, barua pepe, na ujumbe mwingine."</string>
<!-- no translation found for permgrouplab_personalInfo (3519163141070533474) -->
<skip />
- <!-- outdated translation 5488050357388806068 --> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ufikiaji wa moja kwa moja wa anwani zako na kalenda zilizohifadhiwa kwenye simu."</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ufikiaji wa moja kwa moja wa anwani zako na kalenda iliyohifadhiwa kwenye kompyuta ndogo."</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Ufikiaji wa moja kwa moja wa anwani zako na kalenda zilizohifadhiwa kwenye simu."</string>
<!-- no translation found for permgrouplab_location (635149742436692049) -->
<skip />
@@ -274,7 +266,7 @@
<skip />
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Vipengele vinahitaji tu kwa watengenezaji programu."</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Hifadhi"</string>
- <!-- outdated translation 9203302214915355774 --> <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Fikia kadi ya SD."</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Fikia hifadhi ya USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Fikia kadi ya SD."</string>
<!-- no translation found for permlab_statusBar (7417192629601890791) -->
<skip />
@@ -293,16 +285,20 @@
<!-- no translation found for permlab_receiveMms (8894700916188083287) -->
<skip />
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Huruhusu programu kupokea na kuchakata ujumbe wa MMS. Programu mbaya za kompyuta huenda zikafuatilia ujumbe wako au kuzifuta bila kukuonyesha."</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<!-- no translation found for permlab_sendSms (5600830612147671529) -->
<skip />
<string name="permdesc_sendSms" msgid="1946540351763502120">"Huruhusu programu kutuma ujumbe wa SMS. Programu hasidi huenda zikakugharimu pesa kwa kutuma ujumbe bila uthibitisho wako."</string>
<!-- no translation found for permlab_readSms (4085333708122372256) -->
<skip />
- <!-- outdated translation 3002170087197294591 --> <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Huruhusu programu kusoma SMS zilizohifadhiwa kwenye kompyuta yako ndogo au kadi ya SIM. Huenda programu hasidi zikasoma SMS zako za siri."</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Huruhusu programu kusoma ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikasoma ujumbe wako wa siri."</string>
<!-- no translation found for permlab_writeSms (6881122575154940744) -->
<skip />
- <!-- outdated translation 6299398896177548095 --> <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Huruhusu programu kuandika ujumbe wa SMS uliohifadhiwa kwenye kompyuta yako au kadi ya SIM. Huenda programu hasidi zikafuta ujumbe wako."</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Huruhusu programu kuandika kwa ujumbe wa SMS uliohifadhiwa kwenye simu yako au kadi ya SIM. Programu mbaya za kompyuta huenda zikafuta ujumbe wako."</string>
<!-- no translation found for permlab_receiveWapPush (8258226427716551388) -->
<skip />
@@ -335,13 +331,17 @@
<!-- no translation found for permlab_dump (1681799862438954752) -->
<skip />
<string name="permdesc_dump" msgid="2198776174276275220">"Huruhusu programu kuepua hali ya ndani ya mfumo. Programu mbaya za kompyuta huenda zikaepua viwango vikubwa vya maelezo ya kibinafsi na salama ambayo kwa kawaida hazipaswi kuhitaji."</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Humzuia mtumiaji dhidi ya kubadilisha kwa programu nyingine ya kompyuta."</string>
<!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) -->
<skip />
- <!-- outdated translation 3228701938345388092 --> <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Huruhusu programu kusimamia na kudhibiti jinsi mfumo unavyozindua shughuli. Programu mbaya za kompyuta huenda zikahatarisha mfumo kabisa. Kibali hiki kinahitajika tu kwa utengenezaji, sio kwa utumiaji wa kawaida wa simu."</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Huruhusu programu kufuatilia na kudhibiti jinsi mfumo unavyozindua shughuli. Huenda programu hasidi zikahatarisha mfumo kabisa. Kibali hiki kinahitajika tu kwa utengenezaji, sio kwa matumizi ya kawaida."</string>
<!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) -->
<skip />
<string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Huruhusu programu kutangaza notisi kwamba furushi la programu imeondolewa. Programu mbaya za kompyuta huenda zikatumia hii ili kuua programu nyingine ya kompyuta."</string>
@@ -369,7 +369,7 @@
<string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Huruhusu uundaji wa madirisha ambayo yamekusudiwa kutumiwa na kiolesura cha mtumiaji cha mfumo wa ndani. Haipaswi kutumiwa na programu za kawaida za kompyuta."</string>
<!-- no translation found for permlab_systemAlertWindow (3372321942941168324) -->
<skip />
- <!-- outdated translation 5109622689323490558 --> <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Huruhusu programu kuonyesha madirisha ya tahadhari ya mfumo. Programu mbaya za kompyuta zinaweza kuchukua skrini yote kwenye simu."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Huruhusu programu kuonyesha madirisha ya tahadhari ya mfumo. Programu hasidi zinaweza kuchukua skrini nzima."</string>
<!-- no translation found for permlab_setAnimationScale (2805103241153907174) -->
<skip />
<string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Huruhusu programu kubadilisha kasi ya jumla ya uhuishaji (Uhuisho wa haraka zaidi au polepole zaidi) wakati wowote."</string>
@@ -378,7 +378,7 @@
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Huruhusu programu za kompyuta kuunda na kusimamia alama mbadala zao, kwa hivyo kupita mpangilio wao wa kawaida wa Z. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
<!-- no translation found for permlab_injectEvents (1378746584023586600) -->
<skip />
- <!-- outdated translation 3946098050410874715 --> <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Huruhusu programu kuwasilisha matukio yake yenyewe ya uingizaji (ubofyaji kitufe, n.k.) kwa programu zingine za kompyuta. Programu mbaya za kompyuta zinaweza kutumia hii ili kudhibiti simu."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Huruhusu programu kuwasilisha matukio yake yenyewe ya uingizaji (vibonyezo vya vitufe, nk.) kwa programu zingine. Programu hasidi zinaweza kutumia hii ili kuchukua husukani mwa kompyuta ndogo."</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Huruhusu programu kuwasilisha matukio yake yenyewe ya uingizaji (ubofyaji kitufe, n.k.) kwa programu zingine za kompyuta. Programu mbaya za kompyuta zinaweza kutumia hii ili kudhibiti simu."</string>
<!-- no translation found for permlab_readInputState (469428900041249234) -->
<skip />
@@ -422,20 +422,20 @@
<string name="permdesc_installPackages" msgid="526669220850066132">"Huruhusu programu kusakinisha furushi mpya au zilizosasishwa za Android. Programu mbaya za kompyuta zinaweza kusababisha hii kuongeza programu mpya za kompyuta na vibali visivyo na mpangilio vyenye nguvu."</string>
<!-- no translation found for permlab_clearAppCache (4747698311163766540) -->
<skip />
- <!-- outdated translation 7740465694193671402 --> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Huruhusu programu kuwezesha nafasi kwenye simu kwa kufuta faili katika saraka ya kache ya programu. Kwa kawaida ufikiaji umezuiwa sana kwa mchakato wa mfumo."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Huruhusu programu kupata nafasi ya kuhifadhi ya kompyuta ndogo kwa kufuta faili katika saraka ya kache ya programu. Ufikiaji kwa kawaida huwa umezuiliwa kwa mchakato wa mfumo."</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Huruhusu programu kuwezesha nafasi kwenye simu kwa kufuta faili katika saraka ya kache ya programu. Kwa kawaida ufikiaji umezuiwa sana kwa mchakato wa mfumo."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Sogeza rasilimali za programu"</string>
<string name="permdesc_movePackage" msgid="6323049291923925277">"Huruhusu programu kwa sogeza rasilimali za programu kutoka kwa midia ya ndani hadi nje na kurudia tena."</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"soma kumbukumbu ya data muhimu"</string>
- <!-- outdated translation 8896449437464867766 --> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Huruhusu programu kusoma kutoka kwa mfiumo wa faili tofauti za kumbukumbu. Hii inairuhusu kugundua habari ya jumla kuhusu kile unachokifanya kwa simu, kwa kawaida ikijumlisha habari binafsi au faragha."</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Huruhusu programu kusoma kutoka kwa faili mbalimbali za kumbukumbu za mfumo. Hii huiruhusu kutambua maelezo ya jumla kuhusu unachofanya na kompyuta ndogo, kwa hivyo kujumuisha maelezo ya kibinafsi na ya siri."</string>
<string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Huruhusu programu kusoma kutoka kwa mfiumo wa faili tofauti za kumbukumbu. Hii inairuhusu kugundua habari ya jumla kuhusu kile unachokifanya kwa simu, kwa kawaida ikijumlisha habari binafsi au faragha."</string>
<!-- no translation found for permlab_diagnostic (8076743953908000342) -->
<skip />
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Huruhusu programu kusoma na kuandika kwa nyenzo yoyote inayomilikiwa na kikundi cha diag; kwa mfano, faili katika/dev. Huenda hii ikaathiri udhabiti na usalama wa mfumo. Hii inapaswa kutumia TU na vikagua matatizo mahsusi vya maunzi na mtengenezaji au opereta."</string>
<!-- no translation found for permlab_changeComponentState (79425198834329406) -->
<skip />
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Huruhusu programu kubadilisha kama kijenzi cha programu nyingine ya kompyuta kimewezeshwa au la. Programu mbaya za kompyuta zinaweza kutumia hii ili kulemaza uwezo muhimu wa simu. Huduma inapaswa kutumiwa na kibali, kwa kuwa kuna uwezekano wa kupata vijenzi vya programu katika hali isiyoweza kutumiwa, isiyoambatana au usiyodhabiti."</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Huruhusu programu kubadilisha kama kijenzi cha programu nyingine ya kompyuta kimewezeshwa au la. Programu mbaya za kompyuta zinaweza kutumia hii ili kulemaza uwezo muhimu wa simu. Huduma inapaswa kutumiwa na kibali, kwa kuwa kuna uwezekano wa kupata vijenzi vya programu katika hali isiyoweza kutumiwa, isiyoambatana au usiyodhabiti."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Huruhusu programu kubadilisha kama kijenzi cha programu nyingine kimewezeshwa au la. Programu hasidi zinaweza kutumia hii ili kulemaza uwezo muhimu wa kompyuta ndogo. Umakini lazima utumike na kibali hiki, kwa kuwa kuna uwezekano wa kupata vijenzi vya programu katika hali isiyoweza kutumiwa, isiyolingana, au isiyodhabiti."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Huruhusu programu kubadilisha kama kijenzi cha programu nyingine kimewezeshwa au la. Programu hasidi zinaweza kutumia hii ili kulemaza uwezo muhimu wa simu. Umakini lazima utumike na kibali hiki, kwa kuwa kuna uwezekano wa kupata vijenzi vya programu katika hali isiyoweza kutumiwa, isiyolingana, au isiyodhabiti."</string>
<!-- no translation found for permlab_setPreferredApplications (3393305202145172005) -->
<skip />
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Huruhusu programu kurekebisha programu zako za kompyuta unazopendelea. Hii inaweza kuruhusu programu mbaya za kompyuta kubadilisha polepole programu za kompyuta ambazo zinaendeshwa, kwa hivyo kughushi programu zako zilizopo za kompyuta ili kukusanya data za kibinafsi kutoka kwako."</string>
@@ -449,22 +449,30 @@
<string name="permdesc_writeGservices" msgid="6602362746516676175">"Huruhusu programu kurekebisha ramani ya huduma za Google. Haipaswi kutumiwa na programu za kawaida za kompyuta."</string>
<!-- no translation found for permlab_receiveBootCompleted (7776779842866993377) -->
<skip />
- <!-- outdated translation 698336728415008796 --> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Huruhusu programu kujiwasha upya punde tu mfumo unapokamilisha kuwasha. Hii inaweza kuifanya ichukue muda mrefu zaidi kuanzisha simu na kuruhusu programu kupunguza kasi ya simu kwa jumla kwa kuendesha kila wakati."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Huruhusu programu kujianzisha yenyewe punde tu mfumo unapokamilisha kuwaka. Hii inaweza kuifanya ichukue muda mrefu zaidi kuanzisha kompyuta ndogo na kuruhusu programu kupunguza kasi ya kifaa kwa jumla kwa kuendeshwa kila wakati."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Huruhusu programu kujiwasha upya punde tu mfumo unapokamilisha kuwasha. Hii inaweza kuifanya ichukue muda mrefu zaidi kuanzisha simu na kuruhusu programu kupunguza kasi ya simu kwa jumla kwa kuendesha kila wakati."</string>
<!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
<skip />
- <!-- outdated translation 1920045289234052219 --> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Huruhusu programu kutuma matangazo ya kunata, ambayo hubaki baada ya matangazo kuisha. Programu mbaya za kompyuta zinaweza kufanya simu kuwa polepole au kutokuwa dhabiti kwa kuisababisha itumie kumbukumbu nyingi sana."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Huruhusu programu kutuma matangazo ya kunata, ambayo hubaki baada ya tangazo kuisha. Programu hasidi zinaweza kufanya kompyuta ndogo kuwa polepole au kutokuwa dhabiti kwa kukisababisha kutumia kumbukumbu kupita kiasi."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Huruhusu programu kutuma matangazo ya kunata, ambayo hubaki baada ya matangazo kuisha. Programu mbaya za kompyuta zinaweza kufanya simu kuwa polepole au kutokuwa dhabiti kwa kuisababisha itumie kumbukumbu nyingi sana."</string>
<!-- no translation found for permlab_readContacts (6219652189510218240) -->
<skip />
- <!-- outdated translation 3371591512896545975 --> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Huruhusu programu kusoma data zote za anwani zilizohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii kutuma data yako kwa watu wengine."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Huruhusu programu kusoma data yote ya anwani (anwani) iliyohifadhiwa kwenye kompyuta yako ndogo. Programu hasidi zinaweza kutumia hii ili kutuma data yako kwa watu wengine."</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Huruhusu programu kusoma data zote za anwani zilizohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii kutuma data yako kwa watu wengine."</string>
<!-- no translation found for permlab_writeContacts (644616215860933284) -->
<skip />
- <!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Huruhusu programu kurekebisha data ya anwani iliyohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kufuta au kurekebisha data ya anwani yako."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Huruhusu programu kurekebisha data ya anwani (anwani) iliyohifadhiwa kwenye kompyuta yako ndogo. Programu hasidi zinaweza kutumia hii ili kufuta au kurekebisha data yako ya anwani."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Huruhusu programu kurekebisha data ya anwani iliyohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kufuta au kurekebisha data ya anwani yako."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"soma matukio ya kalenda"</string>
- <!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kutuma matukio yako ya kalenda kwa watu wengine."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye kompyuta yako ndogo. Programu hasidi zinaweza kutumia hii ili kutuma data yako kwa watu wengine."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Huruhusu programu kusoma matukio yote ya kalenda yaliyohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kutuma matukio yako ya kalenda kwa watu wengine."</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"ongeza au rekebisha matukio ya kalenda na tuma barua pepe kwa wageni"</string>
<string name="permdesc_writeCalendar" msgid="2988871373544154221">"Inaruhusu programu kwa kuongeza au kubadilisha matukio kwenye kalenda yako, ambayo inaweza kutuma barua pepe kwa wageni. Programu hasidi zinaweza kutumia hii kwa kuzima au kubadilisha matukio ya kalenda kwa kutuma barua pepe kwa wageni."</string>
@@ -478,11 +486,11 @@
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Unda vyanzo vya mahali pa jaribio ili kujaribu. Programu mbaya za kompyuta zinaweza kutumia hii ili kuandikiza mahali na/au hali iliyorejeshwa na vyanzo halisi vya mahali kama vile watoa huduma za GPS au Mtandao au kusimamia na kuripoti mahali pako kwa chanzo cha nje."</string>
<!-- no translation found for permlab_accessFineLocation (8116127007541369477) -->
<skip />
- <!-- outdated translation 7411213317434337331 --> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Fikia vyanzo bora vya mahali kama vile Mfumo wa Mkao Ulimwengu kote kwenye simu, mahali popote inapopatikana. Programu mbaya za kompyuta zinaweza kutumia hii ili kubainisha mahali ulipo, na huenda ikatumia nguvu zaidi ya betri."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Fikia vyanzo vizuri vya mahali kama vile Mfumo wa Kugundua Mahali Ulimwenguni kwenye kompyuta ndogo, unapopatikana. Programu hasidi zinaweza kutumia hili kubainisha mahali ulipo, na huenda ikatumia nishati zaidi ya betri."</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Fikia vyanzo bora vya mahali kama vile Mfumo wa Mkao Ulimwengu kote kwenye simu, mahali popote inapopatikana. Programu mbaya za kompyuta zinaweza kutumia hii ili kubainisha mahali ulipo, na huenda ikatumia nguvu zaidi ya betri."</string>
<!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) -->
<skip />
- <!-- outdated translation 8235655958070862293 --> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Fikia vyanzo vya mahali kama vile hifadhidata ya mtandao wa simu za mkononi ili kubainisha mahali pa simu palipokaribu, kama panapatikana. Programu mbaya za kompyuta zinaweza kutumia hii ili kubainisha mahali ulipo pa karibu."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Fikia vyanzo vya mahali pasipo laini kama vile hifadhidata ya mtandao wa simu za mkononi ili kubainisha mahali karibu pa kompyuta ndogo, inapopatikana. Programu hasidi zinaweza kutumia hii ili kubainisha ukaribu wa mahali ulipo."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Fikia vyanzo vya mahali kama vile hifadhidata ya mtandao wa simu za mkononi ili kubainisha mahali pa simu palipokaribu, kama panapatikana. Programu mbaya za kompyuta zinaweza kutumia hii ili kubainisha mahali ulipo pa karibu."</string>
<!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) -->
<skip />
@@ -498,33 +506,29 @@
<string name="permdesc_recordAudio" msgid="6493228261176552356">"Huruhusu programu kufikia njia ya rekodi ya sikika."</string>
<string name="permlab_camera" msgid="3616391919559751192">"chukua picha na video"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"Huruhusu programu kuchukua picha na video kwa kamera. Hii huruhusu programu kwa wakati wowote kukusanya taswira ambazo kamera inaona."</string>
- <!-- no translation found for permlab_brick (2961292205764488304) -->
- <skip />
- <!-- no translation found for permlab_brick (8337817093326370537) -->
- <skip />
- <!-- outdated translation 5569526552607599221 --> <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Huruhusu programu kulemaza simu yote kabisa. Hii ni hatari sana."</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"lemaza kompyuta ndogo kabisa"</string>
+ <!-- outdated translation 2961292205764488304 --> <string name="permlab_brick" product="default" msgid="8337817093326370537">"lemaza kompyuta ndogo kabisa"</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Huruhusu programu kulemaza kompyuta yote ndogo kabisa. Hii ni hatari sana."</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"Huruhusu programu kulemaza simu yote kabisa. Hii ni hatari sana."</string>
- <!-- no translation found for permlab_reboot (3436634972561795002) -->
- <skip />
- <!-- no translation found for permlab_reboot (2898560872462638242) -->
- <skip />
- <!-- outdated translation 7914933292815491782 --> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Huruhusu programu kulazimisha simu kuwasha."</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"lazimisha kompyuta ndogo kuwaka upya"</string>
+ <!-- outdated translation 3436634972561795002 --> <string name="permlab_reboot" product="default" msgid="2898560872462638242">"lazimisha kompyuta ndogo kuwaka upya"</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Huruhusu programu kulazimisha kompyuta ndogo kuwashwa upya."</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Huruhusu programu kulazimisha simu kuwasha."</string>
<!-- no translation found for permlab_mount_unmount_filesystems (1761023272170956541) -->
<skip />
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Huruhusu programu kuweka na kuondoa mifumo ya faili ya hifadhi inayoweza kuondolewa."</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"fomati hifadhi ya nje"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Huruhusu programu kufomati hifadhi inayoweza kuondolewa."</string>
- <!-- outdated translation 1070364079249834666 --> <string name="permlab_asec_access" msgid="3411338632002193846">"pata habari ya uhifadhi salama"</string>
- <!-- outdated translation 7691616292170590244 --> <string name="permdesc_asec_access" msgid="8820326551687285439">"Huruhusu programu kwa kupata habari ya uhifadhi salama."</string>
- <!-- outdated translation 7312078032326928899 --> <string name="permlab_asec_create" msgid="6414757234789336327">"unda usalama wa uhifadhi"</string>
- <!-- outdated translation 7041802322759014035 --> <string name="permdesc_asec_create" msgid="2621346764995731250">"Huruhusu programu kwa kuunda hifadhi salama"</string>
- <!-- outdated translation 7787322878955261006 --> <string name="permlab_asec_destroy" msgid="526928328301618022">"haribu uhifadhi salama"</string>
- <!-- outdated translation 5740754114967893169 --> <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Huruhusu programu kwa kuharibu hifadhi salama."</string>
- <!-- outdated translation 7517449694667828592 --> <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"angika/angua uhifadhi salama"</string>
- <!-- outdated translation 5438078121718738625 --> <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Huruhusu programu kwa kuangika/kuangua uhifadhi salama."</string>
- <!-- outdated translation 5685344390439934495 --> <string name="permlab_asec_rename" msgid="7496633954080472417">"patia jina upya hifadhi ya usalama"</string>
- <!-- outdated translation 1387881770708872470 --> <string name="permdesc_asec_rename" msgid="2152829985238876790">"Huruhusu programu kwa kupatia jina upya hifadhi salama"</string>
+ <string name="permlab_asec_access" msgid="3411338632002193846">"pata maelezo juu ya hifadhi ya ndani"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Huruhusu programu kupata maelezo juu ya hifadhi ya ndani."</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"unda hifadhi ya ndani"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Huruhusu programu kuunda hifadhi ya ndani."</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"haribu hifadhi ya ndani"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Huruhusu programu kuharibu hifadhi ya ndani."</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"weka / ondoa hifadhi ya ndani"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Huruhusu programu kuweka / kuondoa hifadhi ya ndani."</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"ipe hifadhi ya ndani jina jipya"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Huruhusu programu kubadilisha jina la hifadhi ya ndani."</string>
<!-- no translation found for permlab_vibrate (7768356019980849603) -->
<skip />
<string name="permdesc_vibrate" msgid="2886677177257789187">"Huruhusu programu kudhibiti kitetemeshi."</string>
@@ -535,10 +539,8 @@
<skip />
<!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
<skip />
- <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
- <skip />
- <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
- <skip />
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"tekeleza itifaki ya MTP"</string>
+ <string name="permdesc_accessMtp" msgid="6532961200486791570">"Huruhusu ufikiaji wa kiendeshaji cha kernel MTP ili kutekeleza itifaki ya USB ya MTP."</string>
<!-- no translation found for permlab_hardware_test (4148290860400659146) -->
<skip />
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Huruhusu programu kudhibiti vifaa mbalimbali kwa lengo la kujaribu maunzi."</string>
@@ -548,7 +550,7 @@
<!-- no translation found for permlab_callPrivileged (4198349211108497879) -->
<skip />
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Huruhusu programu kupiga simu kwa nambari yoyote ya simu, pamoja na nambari za dharura, bila mwingiliano wako. Programu mbaya za kompyuta huenda zikaweka simu zisizofaa kinyume cha sheria kwa huduma za dharura."</string>
- <!-- outdated translation 5604848095315421425 --> <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"anzisha moja kwa moja usanidi wa simu ya CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"anzisha usanidi wa kompyuta ndogo ya CDMA moja kwa moja"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"anzisha moja kwa moja usanidi wa simu ya CDMA"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Huruhusu programu kuanzisha utoaji CDMA. Huenda programu mbaya zikaanzisha utoaji CDMA isivyohitajika."</string>
<!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
@@ -564,21 +566,17 @@
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Huruhusu programu kudhibiti vipengele vya simu vya kifaa. programu yenye kibali hiki inaweza kubadili mitandao, kuwasha na kuzima redio ya simu na mambo kama hayo bila kukuarifu hata kamwe."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"soma hali ya simu na itambue"</string>
<string name="permdesc_readPhoneState" msgid="188877305147626781">"Huruhusu programu kufikia vipengele vya simu vya kifaa. programu yenye kibali hiki inaweza kubaini nambari ya simu na nambari tambulishi ya simu hii, kama simu inatumika, nambari ambayo inapiga imeunganishwa na mambo kama hayo."</string>
- <!-- no translation found for permlab_wakeLock (1531731435011495015) -->
- <skip />
- <!-- no translation found for permlab_wakeLock (573480187941496130) -->
- <skip />
- <!-- outdated translation 7584036471227467099 --> <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Huruhusu programu kuzuia simu dhidi ya kuenda kulala."</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
+ <!-- outdated translation 1531731435011495015 --> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zuia kompyuta ndogo dhidi ya kulala"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Huruhusu programu kuzuia kompyuta ndogo dhidi ya kwenda kulala."</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Huruhusu programu kuzuia simu dhidi ya kuenda kulala."</string>
- <!-- no translation found for permlab_devicePower (2787034722616350417) -->
- <skip />
- <!-- no translation found for permlab_devicePower (4928622470980943206) -->
- <skip />
- <!-- outdated translation 4577331933252444818 --> <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Huruhusu programu kuwasha au kuzima."</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"Washa au zima kompyuta ndogo"</string>
+ <!-- outdated translation 2787034722616350417 --> <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"Washa au zima kompyuta ndogo"</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Huruhusu programu kuwasha au kuzima kompyuta ndogo."</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Huruhusu programu kuwasha au kuzima."</string>
<!-- no translation found for permlab_factoryTest (3715225492696416187) -->
<skip />
- <!-- outdated translation 8136644990319244802 --> <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Endesha kama jaribio la kiwango cha chini cha mtengenezaji, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya simu. Inapatikana tu wakati simu inaendeshwa katika gumzo ya jaribio ya mtengenezaji."</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Endesha kama jaribio la mtengenezaji la kiwango cha chini, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya kompyuta ndogo. Inapatikana tu wakati kompyuta ndogo inaendeshwa katika hali ya jaribio la mtengenezaji."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Endesha kama jaribio la kiwango cha chini cha mtengenezaji, kwa hivyo kuruhusu ufikiaji kamili wa maunzi ya simu. Inapatikana tu wakati simu inaendeshwa katika gumzo ya jaribio ya mtengenezaji."</string>
<!-- no translation found for permlab_setWallpaper (6627192333373465143) -->
<skip />
@@ -590,17 +588,17 @@
<skip />
<string name="permdesc_masterClear" msgid="5033465107545174514">"Huruhusu programu kuweka upya kabisa mfumo kwa mipangilio yake ya kiwanda, kwa hivyo kufuta data zote, usanidi, na programu za kompyuta zilizosanidiwa."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"weka muda"</string>
- <!-- outdated translation 667294309287080045 --> <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Huruhusu programu kwa kubadilisha muda wa saa ya simu."</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Huruhusu programu kubadilisha muda wa saa ya kompyuta ndogo."</string>
<string name="permdesc_setTime" product="default" msgid="667294309287080045">"Huruhusu programu kwa kubadilisha muda wa saa ya simu."</string>
<!-- no translation found for permlab_setTimeZone (2945079801013077340) -->
<skip />
- <!-- outdated translation 1902540227418179364 --> <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Huruhusu programu kubadilisha ukunda wa saa wa simu."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Huruhusu programu kubadilisha ukanda saa wa kompyuta ndogo."</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Huruhusu programu kubadilisha ukunda wa saa wa simu."</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"tenda kama Huduma ya Meneja wa Akaunti"</string>
<string name="permdesc_accountManagerService" msgid="6056903274106394752">"Huruhusu programu kupiga simu kwa Wahalalishaji Akaunti"</string>
<!-- no translation found for permlab_getAccounts (4549918644233460103) -->
<skip />
- <!-- outdated translation 6839262446413155394 --> <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Huruhusu programu kupata orodha ya akaunti zinazojulikana na simu."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Huruhusu programu kupata orodha ya akaunti inayojulikana na kompyuta ndogo."</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Huruhusu programu kupata orodha ya akaunti zinazojulikana na simu."</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"tenda kama mhalalishaji"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Huruhusu programu kutumia uwezo wa kihalalishaji akaunti wa KisimamiaAkaunti, pamoja na kuunda akaunti na kupata na kuweka manenosiri yao."</string>
@@ -634,19 +632,17 @@
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Huruhusu programu kupokea paketi zisizoelekezwa moja kwa moja kwa kifaa chako. Hii inawezakuwa muhimu wakati wa kutambua huduma zinazotambuliwa karibu na eneo hilo. Hutumia nguvu zaidi kuliko midi isiyo ya matangazo anuwai."</string>
<!-- no translation found for permlab_bluetoothAdmin (1092209628459341292) -->
<skip />
- <!-- outdated translation 7256289774667054555 --> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Huruhusu programu kusanidi simu ya ndani ya Bluetooth, na kutambua na kulinganisha na vifaa vya mbali."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Huruhusu programu kusanidi kompyuta ndogo ya karibu ya Bluetooth na kutambua na kulinganisha na vifaa vya mbali."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Huruhusu programu kusanidi simu ya ndani ya Bluetooth, na kutambua na kulinganisha na vifaa vya mbali."</string>
<!-- no translation found for permlab_bluetooth (8361038707857018732) -->
<skip />
- <!-- outdated translation 762515380679392945 --> <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Huruhusu programu kuangalia usanidi wa simu ya ndani ya Bluetooth, na kufanya na kukubali maunganisho na vifaa vilivyolinganishwa."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Huruhusu programu kuona usanidi wa kompyuta ndogo ya karibu ya Bluetooth, na kuwezesha na kukubali miunganisho na vifaa vilivyolinganishwa."</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Huruhusu programu kuangalia usanidi wa simu ya ndani ya Bluetooth, na kufanya na kukubali maunganisho na vifaa vilivyolinganishwa."</string>
- <!-- no translation found for permlab_nfc (4423351274757876953) -->
- <skip />
- <!-- no translation found for permdesc_nfc (9171401851954407226) -->
- <skip />
+ <string name="permlab_nfc" msgid="4423351274757876953">"dhibiti Mawasiliano Karibu na Uga"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Huruhusu programu kuwasiliana na lebo za Mawasiliano ya Karibu na Uga (NFC), kadi, na visomaji."</string>
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<!-- no translation found for permlab_disableKeyguard (4977406164311535092) -->
<skip />
@@ -671,41 +667,45 @@
<string name="permdesc_readDictionary" msgid="1082972603576360690">"Huruhusu programu kusoma maneno yoyote ya kibinafsi, majina na vifungu ambavyo huenda mtumiaji amevihifadhi katika kamusi ya mtumiaji."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"andika kwa kamusi iliyofasiliwa na mtumiaji"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"Huruhusu programu kuandika maneno mapya katika kamusi ya mtumiaji."</string>
- <!-- outdated translation 8079403759001777291 --> <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"rekebisha/futa maudhui ya kadi ya SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"rekebisha/futa maudhui ya hifadhi ya USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"rekebisha/futa maudhui ya kadi ya SD"</string>
- <!-- outdated translation 6643963204976471878 --> <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Huruhusu programu kuandika kwenye kadi ya SD."</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Huruhusu programu kuandika kwenye hifadhi ya USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Huruhusu programu kuandika kwenye kadi ya SD."</string>
- <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
- <skip />
- <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
- <skip />
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"badilisha/futa maudhui ya hifadhi ya media ya ndani."</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Huruhusu programu kurekebisha maudhui ya hifadhi ya media ya ndani."</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za kache"</string>
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Huruhusu programu kusoma na kuandika mfumo wa faili ya kache."</string>
- <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+ <string name="permlab_use_sip" msgid="5986952362795870502">"piga/pokea simu za mtandao"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Huruhusu programu kutumia huduma ya SIP ili kupiga/kupokea simu za wavuti."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
<skip />
- <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
<skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Dhibiti urefu na vibambo vilivyoruhusiwa kwenye manenosiri ya kufungua skrini"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
- <!-- outdated translation 7227578260165172673 --> <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Chunguza idadi ya manenosiri yasiyosahihi yaliyoingizwa wakati wa kufungua skrini, na funga simu au futa data yote ya simu ikiwa manenosiri mengi yameingizwa kimakosa"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Fuatilia idadi ya manenosiri yasiyo sahihi yaliyoingizwa wakati wa kufungua skrini, na ufunge kompyuta ndogo au futa data yote ya kompyuta ndogo kama kuna manenosiri mengi sana yasiyo sahihi yaliyoingizwa"</string>
<string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Chunguza idadi ya manenosiri yasiyosahihi yaliyoingizwa wakati wa kufungua skrini, na funga simu au futa data yote ya simu ikiwa manenosiri mengi yameingizwa kimakosa"</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"Badilisha nenosiri la kufungua skrini"</string>
<string name="policydesc_resetPassword" msgid="5391240616981297361">"Badilisha nenosiri la kufungua skrini"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Funga skrini"</string>
<string name="policydesc_forceLock" msgid="5696964126226028442">"Dhibiti jinsi na wakati skrini inapofunga"</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Futa data zote"</string>
- <!-- outdated translation 7669895333814222586 --> <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Futa data ya simu bila ya ilani, kwa utendakazi wa kuweka data kwa ujumla"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Futa data ya kompyuta ndogo bila ilani, kwa kutekeleza weka upya data ya kiwandani"</string>
<string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Futa data ya simu bila ya ilani, kwa utendakazi wa kuweka data kwa ujumla"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Weka mbadala wa kifaa cha ulimwengu"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Weka kifaa mbadala cha ulimwengu kitakachotumiwa wakati wa kuwezesha sera. Msimamizi wa kwanza wa kifaa pekee anaweka matekelezo mbadala ya ulimwengu."</string>
- <!-- no translation found for policylab_expirePassword (885279151847254056) -->
+ <!-- outdated translation 2314569545488269564 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Weka muda wa kuisha wa nenosiri"</string>
+ <!-- outdated translation 7276906351852798814 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Dhibiti muda kabla ya nenosiri la kufunga skrini kuhitajika kubadilishwa"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Weka msimbo fiche wa hifadhi"</string>
+ <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Inahitaji kwamba data ya programu iliyohifadhiwa ifichamishwe"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
- <!-- no translation found for policydesc_expirePassword (4844430354224822074) -->
- <skip />
- <!-- no translation found for policylab_encryptedStorage (8901326199909132915) -->
- <skip />
- <!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
<skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Nyumbani"</item>
@@ -771,11 +771,10 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Kiunda ujumbe cha Kazini"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Msaidizi"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
- <!-- no translation found for eventTypeCustom (7837586198458073404) -->
- <skip />
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Maalum"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"Siku ya kuzaliwa"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Maadhimisho"</string>
- <!-- outdated translation 5834288791948564594 --> <string name="eventTypeOther" msgid="7388178939010143077">"Tukio"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"Nyinginezo"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"Maalum"</string>
<string name="emailTypeHome" msgid="449227236140433919">"Nyumbani"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Kazi"</string>
@@ -802,41 +801,32 @@
<string name="orgTypeWork" msgid="29268870505363872">"Kazi"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"Nyinginezo"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"Maalum"</string>
- <!-- no translation found for relationTypeCustom (3542403679827297300) -->
- <skip />
- <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
- <skip />
- <!-- no translation found for relationTypeBrother (8757913506784067713) -->
- <skip />
- <!-- no translation found for relationTypeChild (1890746277276881626) -->
- <skip />
- <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
- <skip />
- <!-- no translation found for relationTypeFather (5228034687082050725) -->
- <skip />
- <!-- no translation found for relationTypeFriend (7313106762483391262) -->
- <skip />
- <!-- no translation found for relationTypeManager (6365677861610137895) -->
- <skip />
- <!-- no translation found for relationTypeMother (4578571352962758304) -->
- <skip />
- <!-- no translation found for relationTypeParent (4755635567562925226) -->
- <skip />
- <!-- no translation found for relationTypePartner (7266490285120262781) -->
- <skip />
- <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
- <skip />
- <!-- no translation found for relationTypeRelative (1799819930085610271) -->
- <skip />
- <!-- no translation found for relationTypeSister (1735983554479076481) -->
- <skip />
- <!-- no translation found for relationTypeSpouse (394136939428698117) -->
- <skip />
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Maalum"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"Msaidizi"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Kaka"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Mtoto"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Mwenzi wa Nyumbani"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Baba"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Rafiki"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Mdhibiti"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Mama"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"Mzazi"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Mshirika"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Alipendekezwa na"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Ndugu"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Dada"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Mwenzi wa Ndoa"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Maalum"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Nyumbani"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kazi"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Nyinginezo"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ingiza msimbo wa PIN"</string>
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
+ <skip />
<!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
<skip />
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ingiza nenosiri kwa kufungua"</string>
@@ -869,12 +859,14 @@
<skip />
<!-- no translation found for lockscreen_missing_sim_message_short (7381499217732227295) -->
<skip />
- <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
- <skip />
- <!-- no translation found for lockscreen_missing_sim_message (2186920585695169078) -->
- <skip />
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna kadi ya SIM katika kompyuta ndogo."</string>
+ <!-- outdated translation 151659196095791474 --> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna kadi ya SIM katika kompyuta ndogo."</string>
<!-- no translation found for lockscreen_missing_sim_instructions (8874620818937719067) -->
<skip />
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Simu za dharura pekee"</string>
<!-- no translation found for lockscreen_network_locked_message (143389224986028501) -->
<skip />
@@ -888,8 +880,7 @@
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Umechora vibaya ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Tafadhali jaribu tena kati ya sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Haujaingiza nenosiri yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>Tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Haujaingiza PIN yako kwa usahihi mara<xliff:g id="NUMBER_0">%d</xliff:g>tafadhali jaribu tena. "\n\n"baada ya sekunde<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
- <!-- no translation found for lockscreen_failed_attempts_almost_glogin (8687762517114904651) -->
- <skip />
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Umechora mchoro wako wa kufungua vibaya mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%d</xliff:g> yasiyofanikiwa, utaulizwa kufungua kompyuta yako ndogo kwa kutumia njia yako ya kuingia kwa Google."\n\n" Tafadhali jaribu tena kati ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Umechora vibaya ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. Baada ya majaribio zaidi yasiyofaulu <xliff:g id="NUMBER_1">%d</xliff:g>, utaulizwa kufungua simu yako kwa kutumia ingia yako kwenye Google."\n\n" Tafadhali jaribu tena kati ya sekunde <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<!-- no translation found for lockscreen_too_many_failed_attempts_countdown (6251480343394389665) -->
<skip />
@@ -930,22 +921,16 @@
<!-- no translation found for save_password_label (6860261758665825069) -->
<skip />
<string name="double_tap_toast" msgid="1068216937244567247">"Dokezo: gonga mara mbili ili kukuza ndani na nje."</string>
- <!-- no translation found for autofill_this_form (1272247532604569872) -->
- <skip />
- <!-- no translation found for setup_autofill (8154593408885654044) -->
- <skip />
- <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
- <skip />
- <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
- <skip />
- <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
- <skip />
- <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
- <skip />
+ <string name="autofill_this_form" msgid="1272247532604569872">"Mjazo-Atomatiki"</string>
+ <string name="setup_autofill" msgid="8154593408885654044">"Sanidi Mjazo-Atomatiki"</string>
+ <string name="autofill_address_name_separator" msgid="2504700673286691795">" Kishika nafasi "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"soma historia na alamisho za Kivinjari"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Huruhusu programu kusoma URL zote ambazo Kivinjari imetembelea, na alamisho zile zingine zote za Kivinjari."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"andika historia ya Kivinjari na alamisho"</string>
- <!-- outdated translation 945571990357114950 --> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Huruhusu programu kurekebisha historia au alamisho za Kivinjari zilizohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kufuta au kurekebisha data ya Kivinjari chako."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Huruhusu programu kurekebisha historia ya Kivinjari au alamisho zilizohifadhiwa kwenye kompyuta yako ndogo. Programu hasidi zinaweza kutumia hii ili kufuta au kurekebisha data ya Kivinjari chako."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Huruhusu programu kurekebisha historia au alamisho za Kivinjari zilizohifadhiwa kwenye simu yako. Programu mbaya za kompyuta zinaweza kutumia hii ili kufuta au kurekebisha data ya Kivinjari chako."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"weka kengele kwenye saa ya kengele"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Huruhusu programu kuweka kengele kwenye programu iliyosakinishwa ya saa ya kengele. Baadhi ya programu zasaa ya kengele hazingeweza kurekebisha kipengele hiki."</string>
@@ -1096,8 +1081,7 @@
<skip />
<!-- no translation found for paste (5629880836805036433) -->
<skip />
- <!-- no translation found for pasteDisabled (7259254654641456570) -->
- <skip />
+ <string name="pasteDisabled" msgid="7259254654641456570">"Hakuna cha kubandika"</string>
<!-- no translation found for copyUrl (2538211579596067402) -->
<skip />
<string name="selectTextMode" msgid="6738556348861347240">"Chagua maandishi"</string>
@@ -1106,10 +1090,8 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"Vitendo vya maandishi"</string>
<!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
<skip />
- <!-- no translation found for low_internal_storage_view_text (4231085657068852042) -->
- <skip />
- <!-- no translation found for low_internal_storage_view_text (635106544616378836) -->
- <skip />
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">" Nafasi ya hifadhi ya kompyuta ndogo inaisha."</string>
+ <!-- outdated translation 4231085657068852042 --> <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">" Nafasi ya hifadhi ya kompyuta ndogo inaisha."</string>
<!-- no translation found for ok (5970060430562524910) -->
<skip />
<!-- no translation found for cancel (6442560571259935130) -->
@@ -1228,10 +1210,8 @@
<skip />
<!-- no translation found for sim_restart_button (4722407842815232347) -->
<skip />
- <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
- <skip />
- <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
- <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
<!-- no translation found for date_time_set (5777075614321087758) -->
<skip />
<!-- no translation found for default_permission_group (2690160991405646128) -->
@@ -1243,13 +1223,11 @@
<string name="usb_storage_activity_title" msgid="2399289999608900443">"Hifadhi Kubwa ya USB"</string>
<!-- no translation found for usb_storage_title (5901459041398751495) -->
<skip />
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Umeunganisha simu yako kwa kompyuta yako kupitia USB. Chagua kitufe cha chini ikiwa unataka kwa kunali faili kati ya kompyuta yako na Kadi yako ya SD ya Android."</string>
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Umeunganisha simu yako kwa kompyuta yako kupitia USB. Chagua kitufe cha chini ikiwa unataka kwa kunali faili kati ya kompyuta yako na Kadi yako ya SD ya Android."</string>
+ <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Umeunganisha kwenye kompyuta yako kupitia USB. Gusa kitufe hapa chini kama unataka kunakili faili kati ya kompyuta yako na hifadhi yako ya USB ya Android."</string>
+ <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Umeunganisha kwenye kompyuta yako kupitia USB. Gusa kitufe hapa chini kama unataka kunakili faili kati ya kompyuta yako na kadi yako ya SD ya Android."</string>
<string name="usb_storage_button_mount" msgid="1052259930369508235">"Wezesha hifadhi ya USB"</string>
- <!-- no translation found for usb_storage_error_message (3276413764430468454) -->
- <skip />
- <!-- no translation found for usb_storage_error_message (120810397713773275) -->
- <skip />
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kuna tatizo la kutumia hifadhi yako ya USB kwa kihifadhi vitu vingi cha USB."</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kuna tatizo la kutumia kadi yako ya SD kwa kihifadhi vitu vingi cha USB."</string>
<!-- no translation found for usb_storage_notification_title (8175892554757216525) -->
<skip />
<!-- no translation found for usb_storage_notification_message (7380082404288219341) -->
@@ -1257,7 +1235,7 @@
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Zima hifadhi ya USB"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Chagua ili kuzima hifadhi ya USB."</string>
<string name="usb_storage_stop_title" msgid="660129851708775853">"USB ya kuhifadhi inatumika"</string>
- <!-- outdated translation 3613713396426604104 --> <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Kabla ya kuzima hifadhi ya USB, hakikisha umeangua (“ondolewa”) kadi yako ya Androids ya SD kutoka kwa kompyuta yako."</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Kabla ya kuzima hifadhi ya USB, hakikisha umeondoa (\"umetema\") hifadhi yako ya USB ya Android kutoka kwenye kompyuta yako."</string>
<string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Kabla ya kuzima hifadhi ya USB, hakikisha umeangua (“ondolewa”) kadi yako ya Androids ya SD kutoka kwa kompyuta yako."</string>
<string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Inazima hifadhi ya USB"</string>
<string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kulikuwa na tatizo la kuzima uhifadhi wa USB. angalia kwa kuhakikisha umeangua mpangishi wa USB, kisha jaribu tena."</string>
@@ -1265,9 +1243,13 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ikiwa utawezesha hifadhi ya UsB, baadhi ya programu unazozitumia zitakoma na huenda zisipatikane hadi uzime hifadhi ya UsB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Uendeshi wa USB umeshindikana"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Sawa"</string>
- <!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fomati kadi ya SD"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fomati hifadhi ya USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fomati kadi ya SD"</string>
- <!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Una uhakika unataka kufomati kadi ya SD? Data zote kwenye kadi yako zitapotea."</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Fomati hifadhi ya USB, unafuta faili zote zilizohifadhiwa hapo? Hatua hii haiwezi kugeuzwa!"</string>
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Una uhakika unataka kufomati kadi ya SD? Data zote kwenye kadi yako zitapotea."</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Fomati"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji USB umeunganishwa"</string>
@@ -1278,28 +1260,28 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string>
- <!-- outdated translation 5457603418970994050 --> <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Inaandaa kadi ya SD"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Inaandaa hifadhi ya USB"</string>
<string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Inaandaa kadi ya SD"</string>
<string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Inakagua hitilafu."</string>
- <!-- outdated translation 780477838241212997 --> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Kadi tupu ya SD"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Hifadhi tupu ya USB"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Kadi tupu ya SD"</string>
- <!-- outdated translation 3817704088027829380 --> <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Kadi ya SD iko tupu au ina mfumo wa faili usiohimiliwa."</string>
+ <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Hifadhi ya USB iko tupu au ina mfumo wa faili usiohimiliwa."</string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Kadi ya SD iko tupu au ina mfumo wa faili usiohimiliwa."</string>
- <!-- outdated translation 6410723906019100189 --> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Kadi ya SD iliyoharibika"</string>
+ <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Hifadhi ya USB iliyoharibika"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Kadi ya SD iliyoharibika"</string>
- <!-- outdated translation 6902531775948238989 --> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Kadi ya SD imeharibika. Huenda ikakubidi uifomati upya."</string>
+ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Hifadhi ya USB imeharibika. Huenda ikakubidi uifomati."</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Kadi ya SD imeharibika. Huenda ikakubidi uifomati upya."</string>
- <!-- outdated translation 6872152882604407837 --> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Kadi ya SD imeondolewa bila kutarajiwa"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Hifadhi ya USB imeondolewa bila kutarajiwa"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Kadi ya SD imeondolewa bila kutarajiwa"</string>
- <!-- outdated translation 7260183293747448241 --> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Toa kadi ya SD kabla ya kuondoa ili kuepuka upotezaji data."</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ondoa hifadhi ya USB kabla ya kuondoa ili kuepuka kupoteza data."</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Toa kadi ya SD kabla ya kuondoa ili kuepuka upotezaji data."</string>
- <!-- outdated translation 6729801130790616200 --> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Ni salama kuondoa kadi ya SD"</string>
+ <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Hifadhi ya USB ni salama kuondoa"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Ni salama kuondoa kadi ya SD"</string>
- <!-- outdated translation 568841278138377604 --> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Unaweza kuondoa kadi ya SD kwa usalama."</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Unaweza kuondoa hifadhi ya USB kwa usalama."</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Unaweza kuondoa kadi ya SD kwa usalama."</string>
- <!-- outdated translation 8902518030404381318 --> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Kadi ya SD iliyotolewa"</string>
+ <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Imeondoa hifadhi ya USB"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Kadi ya SD iliyotolewa"</string>
- <!-- outdated translation 3870120652983659641 --> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Kadi ya SD imeondolewa. Ingiza mpya."</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Hifadhi ya USB imeondolewa. Ingiza media mpya."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Kadi ya SD imeondolewa. Ingiza mpya."</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Hakuna shughuli zinazooana zilizopatikana"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"sasisha takwimu za utumiaji vijenzi"</string>
@@ -1313,8 +1295,7 @@
<string name="ime_action_send" msgid="2316166556349314424">"Tuma"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Ifuatayo"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Kwisha"</string>
- <!-- no translation found for ime_action_previous (1443550039250105948) -->
- <skip />
+ <string name="ime_action_previous" msgid="1443550039250105948">"Iliyotangulia"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Tekeleza"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Piga nambari "\n" kwa kutumia <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Unda anwani "\n" kwa kutumia <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1334,6 +1315,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Itifaki ya Kupitisha Tabaka 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Ufunguo ulioshirikiwa mapema unaotegemea L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Cheti kinachotegemea L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Chagua faili"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Hakuna faili iliyochaguliwa"</string>
<string name="reset" msgid="2448168080964209908">"Weka upya"</string>
@@ -1355,60 +1344,33 @@
<item quantity="one" msgid="8167147081136579439">"Linganisho 1"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ya <xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
- <!-- no translation found for action_mode_done (7217581640461922289) -->
- <skip />
- <!-- no translation found for progress_unmounting (535863554318797377) -->
- <skip />
- <!-- no translation found for progress_unmounting (5556813978958789471) -->
- <skip />
- <!-- no translation found for progress_erasing (4183664626203056915) -->
- <skip />
- <!-- no translation found for progress_erasing (2115214724367534095) -->
- <skip />
- <!-- no translation found for format_error (4320339096529911637) -->
- <skip />
- <!-- no translation found for format_error (1343380371925238343) -->
- <skip />
- <!-- no translation found for media_bad_removal (7960864061016603281) -->
- <skip />
- <!-- no translation found for media_checking (418188720009569693) -->
- <skip />
- <!-- no translation found for media_checking (7334762503904827481) -->
- <skip />
- <!-- no translation found for media_removed (7001526905057952097) -->
- <skip />
- <!-- no translation found for media_shared (5830814349250834225) -->
- <skip />
- <!-- no translation found for media_shared (5706130568133540435) -->
- <skip />
- <!-- no translation found for media_unknown_state (729192782197290385) -->
- <skip />
- <!-- no translation found for share (1778686618230011964) -->
- <skip />
- <!-- no translation found for find (4808270900322985960) -->
- <skip />
- <!-- no translation found for websearch (4337157977400211589) -->
- <skip />
- <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
- <skip />
- <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
- <skip />
- <!-- no translation found for gpsNotifMessage (1374718023224000702) -->
- <skip />
- <!-- no translation found for gpsVerifYes (2346566072867213563) -->
- <skip />
- <!-- no translation found for gpsVerifNo (1146564937346454865) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
- <skip />
- <!-- no translation found for sync_really_delete (8933566316059338692) -->
- <skip />
- <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
- <skip />
- <!-- no translation found for sync_do_nothing (8717589462945226869) -->
- <skip />
+ <string name="action_mode_done" msgid="7217581640461922289">"Kwisha"</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Inaondoa hifadhi ya USB..."</string>
+ <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Inaondoa kadi ya SD..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Inafuta hifadhi ya USB..."</string>
+ <string name="progress_erasing" product="default" msgid="2115214724367534095">"Inafuta kadi ya SD..."</string>
+ <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Imeshindwa kufuta hifadhi ya USB."</string>
+ <string name="format_error" product="default" msgid="1343380371925238343">"Imeshindwa kufuta kadi ya SD."</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"Kadi ya SD iliondolewa kabla ya kuondolewa."</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Hifadhi ya USB inakaguliwa kwa sasa."</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"Kadi ya SD inakaguliwa kwa sasa."</string>
+ <string name="media_removed" msgid="7001526905057952097">"Kadi ya SD imeondolewa."</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Hifadhi ya USB inatumika kwa sasa na kompyuta."</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"Kadi ya SD inatumika kwa sasa na kompyuta."</string>
+ <string name="media_unknown_state" msgid="729192782197290385">"Media ya nje katika hali isiyojulikana."</string>
+ <string name="share" msgid="1778686618230011964">"Shiriki"</string>
+ <string name="find" msgid="4808270900322985960">"Tafuta"</string>
+ <string name="websearch" msgid="4337157977400211589">"Utafutaji Wavuti"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Ombi la mahali kutoka <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Ombi la mahali"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"Imeombwa na <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"Ndiyo"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"Hapana"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"Upeo wa ufutaji umezidishwa"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"Kuna vipengee <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> vilivyofutwa vya <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, akaunti <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Ungetaka kufanya nini?"</string>
+ <string name="sync_really_delete" msgid="8933566316059338692">"Futa vipengee."</string>
+ <string name="sync_undo_deletes" msgid="8610996708225006328">"Tendua ufutaji."</string>
+ <string name="sync_do_nothing" msgid="8717589462945226869">"Usifanye chochote kwa sasa."</string>
<!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
<skip />
<!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
@@ -1435,4 +1397,16 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index 734031f..d73ff99 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -16,4 +16,5 @@
<resources>
<bool name="preferences_prefer_dual_pane">true</bool>
+ <bool name="show_ongoing_ime_switcher">false</bool>
</resources>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index d6a0cdd..13bbac6 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -23,9 +23,6 @@
<!-- see comment in values/config.xml -->
<integer name="config_longPressOnPowerBehavior">2</integer>
- <!-- Show sliding tab before lockscreen -->
- <bool name="config_enableSlidingTabFirst">false</bool>
-
<!-- Enable lockscreen rotation -->
<bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index df1597c..9ffe6b1 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -24,5 +24,25 @@
<dimen name="status_bar_icon_size">32dip</dimen>
<!-- Size of the giant number (unread count) in the notifications -->
<dimen name="status_bar_content_number_size">48sp</dimen>
+
+ <!-- The maximum number of action buttons that should be permitted within
+ an action bar/action mode. This will be used to determine how many
+ showAsAction="ifRoom" items can fit. "always" items can override this. -->
+ <integer name="max_action_buttons">5</integer>
+ <!-- Default height of an action bar. -->
+ <dimen name="action_bar_default_height">56dip</dimen>
+ <!-- Vertical padding around action bar icons. -->
+ <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+ <!-- Text size for action bar titles -->
+ <dimen name="action_bar_title_text_size">18dp</dimen>
+ <!-- Text size for action bar subtitles -->
+ <dimen name="action_bar_subtitle_text_size">14dp</dimen>
+
+ <!-- Size of clock font in LockScreen. -->
+ <dimen name="keyguard_pattern_unlock_clock_font_size">98sp</dimen>
+
+ <!-- Size of status line font in LockScreen. -->
+ <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
+
</resources>
diff --git a/core/res/res/values-sw600dp/styles.xml b/core/res/res/values-sw600dp/styles.xml
index 7515c98..645db13 100644
--- a/core/res/res/values-sw600dp/styles.xml
+++ b/core/res/res/values-sw600dp/styles.xml
@@ -15,27 +15,6 @@
-->
<resources>
- <!-- Status Bar Styles -->
-
- <style name="TextAppearance.StatusBar">
- <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
- </style>
- <style name="TextAppearance.StatusBar.Ticker">
- </style>
- <style name="TextAppearance.StatusBar.Title">
- <item name="android:textStyle">bold</item>
- </style>
-
- <style name="TextAppearance.StatusBar.Icon">
- </style>
- <style name="TextAppearance.StatusBar.EventContent">
- <item name="android:textColor">#ff999999</item>
- <item name="android:textSize">14sp</item>
- </style>
- <style name="TextAppearance.StatusBar.EventContent.Title">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- </style>
-
<style name="TextAppearance.Holo.Widget.TabWidget">
<item name="android:textSize">18sp</item>
<item name="android:textStyle">normal</item>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index be958dc..2eb1b79 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"PUK เก่าที่คุณพิมพ์ไม่ถูกต้อง"</string>
<string name="mismatchPin" msgid="3695902225843339274">"PIN ที่คุณป้อนไม่ตรงกัน"</string>
<string name="invalidPin" msgid="3850018445187475377">"พิมพ์ PIN ซึ่งเป็นเลข 4-8 หลัก"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"พิมพ์รหัส PUK ซึ่งต้องเป็นตัวเลขอย่างน้อย 8 หลัก"</string>
<string name="needPuk" msgid="919668385956251611">"ซิมการ์ดของคุณถูกล็อกด้วย PUK พิมพ์รหัส PUK เพื่อปลดล็อก"</string>
<string name="needPuk2" msgid="4526033371987193070">"พิมพ์ PUK2 เพื่อยกเลิกการปิดกั้นซิมการ์ด"</string>
<string name="ClipMmi" msgid="6952821216480289285">"หมายเลขผู้โทรเข้า"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
<string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"บริการที่ต้องเสียค่าใช้จ่าย"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบหรือลบข้อความของคุณโดยไม่แสดงให้คุณเห็น"</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"รับ MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS แอปพลิเคชันที่เป็นอันตรายอาจตรวจดูหรือลบข้อความของคุณโดยไม่แสดงให้คุณเห็น"</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"ได้รับการกระจายข้อความฉุกเฉิน"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความการกระจายฉุกเฉิน การอนุญาตนี้จะใช้ได้เฉพาะกับแอปพลิเคชันระบบ"</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"ส่งข้อความ SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"อนุญาตให้แอปพลิเคชันส่งข้อความ SMS แอปพลิเคชันที่เป็นอันตรายอาจทำให้คุณเสียค่าใช้จ่ายโดยการส่งข้อความโดยไม่ขอการยืนยันจากคุณ"</string>
<string name="permlab_readSms" msgid="4085333708122372256">"อ่าน SMS หรือ MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"อนุญาตให้แอปพลิเคชันบังคับให้กิจกรรมที่อยู่ด้านหน้าปิดและย้อนกลับ ไม่ควรต้องใช้สำหรับแอปพลิเคชันปกติ"</string>
<string name="permlab_dump" msgid="1681799862438954752">"เรียกดูสถานะภายในของระบบ"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"อนุญาตให้แอปพลิเคชันเรียกข้อมูลสถานะภายในของระบบ แอปพลิเคชันที่เป็นอันตรายอาจเรียกดูข้อมูลส่วนบุคคลและข้อมูลความปลอดภัยได้หลายอย่าง ซึ่งตามปกติไม่ควรต้องใช้"</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ดึงเนื้อหาหน้าจอ"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"อนุญาตให้แอปพลิเคชันดึงเนื้อหาของหน้าต่างที่ใช้งานอยู่ แอปพลิเคชันที่เป็นอันตรายอาจทำการดึงเนื้อหาทั้งหน้าต่างและตรวจสอบข้อความทั้งหมดยกเว้นรหัสผ่าน"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"อนุญาตให้ผู้ถือส่งเนื้อหาไปยังโปรแกรมควบคุมอุปกรณ์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"เปลี่ยนการวางแนวหน้าจอ"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"อนุญาตให้แอปพลิเคชันเปลี่ยนการหมุนหน้าจอได้ตลอดเวลา ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"เปลี่ยนความเร็วของตัวชี้"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"อนุญาตให้แอปพลิเคชันเปลี่ยนความเร็วของตัวชี้ของเมาส์หรือแทร็กแพดได้ตลอดเวลา ไม่จำเป็นสำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"ส่งสัญญาณ Linux ไปยังแอปพลิเคชัน"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"อนุญาตให้แอปพลิเคชันร้องขอให้ส่งสัญญาณแจ้งไปยังกระบวนการที่ยังทำงานอยู่ทั้งหมด"</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"ทำให้แอปพลิเคชันทำงานตลอดเวลา"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"เขียนข้อมูลที่อยู่ติดต่อ"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลรายชื่อติดต่อ (ที่อยู่) ที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลรายชื่อติดต่อของคุณได้"</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลที่อยู่ติดต่อ (ที่อยู่) ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลที่อยู่ติดต่อของคุณได้"</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"อ่านกิจกรรมบนปฏิทิน"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมในปฏิทินของคุณให้แก่ผู้อื่นได้"</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมบนปฏิทินทั้งหมดที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมบนปฏิทินไปหาผู้อื่นได้"</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"ควบคุม Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"อนุญาตให้แอปพลิเคชันสื่อสารกับแท็ก Near Field Communication (NFC) การ์ด และโปรแกรมอ่าน"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"สกัดกั้นและแก้ไขการเข้าใช้งานเครือข่ายทั้งหมด"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"ช่วยให้แอปพลิเคชันสกัดกั้นและตรวจสอบการเข้าใช้งานบนเครือข่ายทั้งหมด เช่น การสร้างการเชื่อมต่อ VPN แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบ เปลี่ยนเส้นทาง หรือแก้ไขแพ็คเก็ตเครือข่ายโดยที่คุณไม่ทราบ"</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"อนุญาตให้แอปพลิเคชันสกัดกั้นและตรวจสอบการเข้าใช้งานเครือข่ายทั้งหมดเพื่อสร้างการเชื่อมต่อ VPN แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบ เปลี่ยนเส้นทาง หรือแก้ไขแพ็คเก็ตเครือข่ายโดยที่คุณไม่ทราบ"</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"ปิดการใช้งานการล็อกปุ่มกด"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"อนุญาตให้แอปพลิเคชันปิดการใช้งานการล็อกปุ่มและการรักษาความปลอดภัยรหัสผ่านที่เกี่ยวข้องใดๆ ตัวอย่างการใช้งานของกรณีนี้คือ โทรศัพท์ปิดการใช้งานการล็อกปุ่มกดเมื่อมีสายเรียกเข้า จากนั้นจึงเปิดการใช้งานการล็อกปุ่มกดใหม่เมื่อวางสายแล้ว"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"อ่านการตั้งค่าการซิงค์แล้ว"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"โทรออก/รับสายอินเทอร์เน็ต"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"อนุญาตให้แอปพลิเคชันใช้บริการ SIP เพื่อโทรออก/รับสายอินเทอร์เน็ต"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"ควบคุมความถี่ในการเปลี่ยนรหัสผ่านล็อกหน้าจอ"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"ตั้งค่าการเข้ารหัสที่เก็บข้อมูล"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"กำหนดว่าแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"บ้าน"</item>
<item msgid="869923650527136615">"มือถือ"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"ที่ทำงาน"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"อื่นๆ"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"ป้อนรหัส PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"ป้อนรหัส PUK และรหัส PIN ใหม่"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"รหัส PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"รหัส PIN ใหม่"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"แตะเพื่อใส่รหัสผ่าน"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"ป้อนรหัสผ่านเพื่อปลดล็อก"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"ป้อน PIN เพื่อปลดล็อก"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ไม่มีซิมการ์ดในโทรศัพท์"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"โปรดใส่ซิมการ์ด"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"โทรฉุกเฉินเท่านั้น"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"ล็อกเครือข่ายไว้"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"ซิมการ์ดถูกล็อกด้วย PUK"</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"หากคุณเปิดที่จัดเก็บข้อมูล USB แอปพลิเคชันบางอย่างที่คุณใช้อยู่จะหยุดและอาจใช้งานไม่ได้จนกว่าคุณจะปิดที่จัดเก็บข้อมูล USB"</string>
<string name="dlg_error_title" msgid="8048999973837339174">"การปฏิบัติงานของ USB ล้มเหลว"</string>
<string name="dlg_ok" msgid="7376953167039865701">"ตกลง"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"ฟอร์แมตที่เก็บข้อมูล USB โดยลบไฟล์ทั้งหมดที่จัดเก็บอยู่ในนั้นหรือไม่ การทำงานนี้ไม่สามารถย้อนกลับได้"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN ตามคีย์ที่ให้ใช้ร่วมกันล่วงหน้า"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/ VPN ตามใบรับรอง"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
<string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"ที่เก็บข้อมูลภายใน"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"การ์ด SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"ที่เก็บข้อมูล USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"แก้ไข..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"ใบรับรองความปลอดภัย"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"ใบรับรองนี้ใช้งานได้"</string>
+ <string name="issued_to" msgid="9032338008819841339">"ออกให้แก่:"</string>
+ <string name="common_name" msgid="5745530093500062357">"ชื่อทั่วไป:"</string>
+ <string name="org_name" msgid="8868889052889991293">"องค์กร:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"หน่วยองค์กร:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"ออกโดย:"</string>
+ <string name="validity_period" msgid="57988851973181309">"อายุการใช้งาน:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"ออกเมื่อ:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"หมดอายุวันที่:"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index b6942a4..760724b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Mali ang na-type mong PUK."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Hindi nagtugma ang ipinasok mong mga PIN."</string>
<string name="invalidPin" msgid="3850018445187475377">"Mag-type ng PIN na 4 hanggang 8 numero."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Mag-type ng PUK na may 8 numbero o mas mahaba."</string>
<string name="needPuk" msgid="919668385956251611">"Na-PUK-lock ang iyong SIM card. I-type ang PUK code upang i-unlock ito."</string>
<string name="needPuk2" msgid="4526033371987193070">"I-type ang PUK2 upang i-unblock ang SIM card."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Papasok na Caller ID"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Naka-ON ang airplane mode"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Naka-OFF ang airplane mode"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Mga serbisyong ginagastusan mo"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Pinapayagan ang application na tumanggap at magproseso ng mga SMS na mensahe. Maaaring subaybayan ng mga nakakahamak na application ang iyong mga mensahe o tanggalin ang mga ito nang hindi ipinapakita sa iyo."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"tumanggap ng MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Pinapayagan ang application na tumanggap at magproseso ng mga MMS na mensahe. Maaaring subaybayan ng mga nakakahamak na application ang iyong mga mensahe o tanggalin ang mga ito nang hindi ipinapakita ang mga ito sa iyo."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"makatanggap ng mga emergency broadcast"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Pinapayagan ang application na mabawi at iproseso ang mga mensahe ng emergency broadcast. Available lang ang pahintulot na ito sa mga system application."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"magpadala ng mga SMS na mensahe"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Pinapayagan ang application na magpadala ng mga SMS na mensahe. Maaaring mapagastos ka ng mga nakakahamak na application sa pamamagitan ng pagpapadala ng mga mensahe nang wala ng iyong kumpirmasyon."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"magbasa ng SMS o MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Pinapayagan ang isang application na puwersahin ang anumang aktibidad na nasa unahan upang isara at bumalik. Hindi kailanman dapat kailanganin para sa mga normal na application."</string>
<string name="permlab_dump" msgid="1681799862438954752">"ibalik ang panloob na katayuan ng system"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Pinapayagan ang application na magbalik ng panloob na katayuan ng system. Maaaring magbalik ang mga nakakahamak na application ng maraming uri ng pribado at secure na impormasyon na hindi nila kailanman normal na kailangan."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"kunin ang nilalaman ng screen"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Pinapayagan ang application na makuha ang nilalaman ng aktibong window. Maaaring kunin ng mga nakakahamak na application ang buong nilalaman ng window at suriin ang lahat ng teksto nito bukod sa mga password."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"bahagyang pag-shutdown"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Inilalagay ang tagapamahala ng aktibidad sa katayuan ng pag-shutdown. Hindi nagsasagawa ng kumpletong pag-shutdown."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Pinapayagan ang holder na magpadala ng mga intensyon sa administrator ng device. Hindi kailanman dapat kailanganin para sa mga normal na application."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"baguhin ang orientation ng screen"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Pinapayagan ang isang application na baguhin ang pag-rotate ng screen anumang oras. Hindi kailanman dapat kailanganin para sa mga normal na application."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"baguhin ang bilis ng pointer"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Pinapayagan ang isang application na baguhin ang bilis ng mouse o trackpad pointer anumang oras. Dapat na hindi kailanman kailanganin para sa mga normal na application."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"magpadala ng mga Linux signal sa mga application"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Pinapayagan ang application na hilinging ipadala ang na-supply na signal sa lahat ng mga paulit-ulit na proseso."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"palaging patakbuhin ang mga application"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"sumulat ng data ng pakikipag-ugnay"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Pinapayagan ang application na baguhin ang data ng contact (address) na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang burahin o baguhin ang data ng iyong contact."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Pinapayagan ang isang application na baguhin ang data ng pakikipag-ugny (address) na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng pakikipag-ugnay."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"basahin ang mga kaganapan sa kalendaryo"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Pinapayagan ang application na basahin ang lahat ng mga kaganapan sa kalendaryo na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa mga ibang tao."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Pinapayagan ang isang application na basahin ang lahat ng mga kaganapan sa kalendaryong nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa ibang tao."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kontrolin ang Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Pinapayagan ang application na makipagkomunika sa mga Near Field Communication (NFC) na tag, card, at reader."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"harangin at baguhin ang lahat ng trapiko ng network"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Pinapayagan ang isang application na harangin at suriin ang lahat ng trapiko ng network, halimbawa ang pagtaguyod ng koneksyon na VPN. Maaaring magsubabay, mag-redirect o magbago ng mga network packet ang mga nakakahamak na application nang hindi mo nalalaman."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Pinapayagan ang isang application na harangin at suriin ang lahat ng trapiko ng network upang magtaguyod ng koneksyon ng VPN. Maaaring sumubaybay, mag-redirect, o magbago ng mga network packet nang hindi mo nalalaman."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"huwag paganahin ang keylock"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pinapayagan ang isang application na huwag paganahin ang keylock at ang anumang nauugnay na seguridad sa password. Ang isang lehitimong halimbawa nito ay ang hindi pagpapagana ng telepono sa keylock kapag nakakatanggap ng papasok na tawag sa telepono, pagkatapos ay muling pagaganahin ang keylock kapag tapos na ang tawag."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"basahin ang mga setting ng sync"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Pinapayagan ang isang application na basahin at isulat ang cache filesystem."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"gumawa/tumanggap ng mga tawag sa Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Pinapayagan ang application upang gamitin ang serbisyong SIP upang gumawa/tumanggap ng mga tawag sa Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Kontrolin kung gaano kadalas dapat na mapalitan ang password sa pag-lock ng screen"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Itakda pag-encrypt ng imbakan"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Hinging naka-encrypt ang nakaimbak na data ng application"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Home"</item>
<item msgid="869923650527136615">"Mobile"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabaho"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Iba pa"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ipasok ang PIN code"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Ilagay ang PUK at bagong PIN code"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK code"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Bagong Pin Code"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"I-touch pra mg-passwrd"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ipasok ang password upang i-unlock"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ipasok ang PIN upang i-unlock"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Walang SIM card sa tablet."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Walang SIM card sa telepono."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Mangyaring magpasok ng SIM card."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Mga pang-emergency na tawag lang"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Naka-lock ang network"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Naka-PUK-lock ang SIM card."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Kung io-on mo ang USB storage, titigil ang ilang application na ginagamit mo at maaaring maging hindi available hanggang sa i-off mo ang USB storage."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Nabigo ang pagpapatakbo ng USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"I-format USB storage"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"I-format ang SD card"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"I-format ang imbakan na USB, na binubura ang lahat ng mga file na nakaimbak doon? Hindi maaaring maibalik ang pagkilos!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Layer 2 Tunneling Protocol"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unang ibinahaging key na batay sa L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Batay sa certificate na L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string>
<string name="reset" msgid="2448168080964209908">"I-reset"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Panloob na Storage"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD Card"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB storage"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"I-edit..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificate na pangseguridad"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Wasto ang certificate na ito."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Ibinigay kay:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Karaniwang pangalan:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Samahan:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unit na pangsamahan:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Ibinigay ni:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Pagpapatunay:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Ibinigay noong:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Mag-e-expire sa:"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e97d834..f9f2a16 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Yazdığınız PUK doğru değil."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Girdiğiniz PIN kodları eşleşmiyor."</string>
<string name="invalidPin" msgid="3850018445187475377">"4 ila 8 rakamdan oluşan bir PIN girin."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"8 veya daha uzun basamaklı bir PUK kodu yazın."</string>
<string name="needPuk" msgid="919668385956251611">"SIM kartınızın PUK kilidi devrede. Kilidi açmak için PUK kodunu yazın."</string>
<string name="needPuk2" msgid="4526033371987193070">"Engellenen SIM kartı açmak için PUK2 kodunu yazın."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Gelen Çağrı Kimliği"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Uçak modu"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Uygulamanın SMS mesajları alıp işlemesine izin verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya bunları size göstermeden silebilir."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"MMS al"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Uygulamanın MMS mesajları almasına ve işlemesine izin verir. Kötü amaçlı uygulamalar mesajlarınızı izleyebilir veya size göstermeden silebilir."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"acil durum yayınlarını al"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Uygulamanın acil durum yayını mesajlarını alıp işlemesine izin verir. Bu izin yalnızca sistem uygulamaları için geçerlidir."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"SMS mesajları gönder"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Uygulamaların SMS mesajları göndermesine izin verir. Kötü amaçlı uygulamalar, onayınızı almadan mesaj göndererek size maliyet çıkarabilir."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"SMS veya MMS oku"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Uygulamaların, ön plandaki herhangi bir etkinliği kapanmaya ve arka plana geçmeye zorlamasına izin verir. Normal uygulamalarda hiçbir zaman gerekmemelidir."</string>
<string name="permlab_dump" msgid="1681799862438954752">"sistemin dahili durumunu al"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Uygulamanın dahili sistem durumunu almasına izin verir. Kötü amaçlı uygulamalar, normalde gerekli olmaması gereken çok çeşitli özel ve koruma altındaki bilgiyi alabilir."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"ekran içeriğini al"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Uygulamanın etkin pencerenin içeriğini almasına izin verir. Kötü amaçlı uygulamalar tüm pencerenin içeriğini alıp şifreler hariç içindeki tüm metni inceleyebilir."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"kısmi kapatma"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Eylem yöneticisini kapalı duruma getirir. Tam kapatma işlemi gerçekleştirmez."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama değişimlerini engelle"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Cihazın sahibinin cihaz yöneticisine amaç göndermesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"ekran yönünü değiştir"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Uygulamaların ekran yönünü istedikleri zaman değiştirmesine izin verir. Normal uygulamalarda hiçbir zaman gerekmemelidir."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"işaretçi hızını değiştir"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Bir uygulamanın herhangi bir zamanda fare veya izleme yüzeyi işaretleme hızını değiştirmesine izin verir. Normal uygulamalar tarafından hiçbir zaman kullanılması gerekmez."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"uygulamalara Linux sinyalleri gönder"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Uygulamaların, sağlanan sinyalin tüm kalıcı işlemlere gönderilmesini istemesine izin verir."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"uygulamayı her zaman çalıştır"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"kişi verileri yaz"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Uygulamaya, tabletinizde depolanan kişi (adres) verilerini değiştirme izni verir. Kötü amaçlı uygulamalar bu işlevi kişi verilerinizi silmek veya değiştirmek için kullanabilir."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Uygulamaların telefonunuzda depolanan kişi (adres) verilerini değiştirmesine izin verir. Kötü amaçlı uygulamalar bu işlevi kişi verilerinizi silmek veya değiştirmek için kullanabilir."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"takvim etkinliklerini oku"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Uygulamaya, tabletinizde depolanan takvim etkinliklerinin tümünü okuma izni verir. Kötü amaçlı uygulamalar bunu, takvim etkinliklerinizi başkalarına göndermek için kullanabilir."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Uygulamaların telefonunuzda depolanan takvim etkinliklerinin tümünü okumasına izin verir. Kötü amaçlı uygulamalar bunu, takvim etkinliklerinizi başkalarına göndermek için kullanabilir."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"Yakın Alan İletişimini denetle"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Bir uyg\'nın Yakın Alan İletişimi etiketleri, kartları ve okuyclr ile iletşm kurmasına izin verir."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"Tüm ağ trafiğine müdahale et ve değişiklik yap"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Bir uygulamanın tüm ağ trafiğine müdahale etmesine ve ağ trafiğini incelemesine izin verir. Uygulama bunu örneğin bir VPN bağlantısı oluşturmak için yapabilir. Kötü niyetli uygulamalar sizin bilginiz dışında ağ paketlerini izleyebilir, yönlendirebilir veya değiştirebilir."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Bir uygulamanın, VPN bağlantısı oluşturmak için tüm ağ trafiğine müdahale etmesine ve ağ trafiğini incelemesine izin verir. Kötü niyetli uygulamalar sizin bilginiz dışında ağ paketlerini izleyebilir, yönlendirebilir veya değiştirebilir."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"tuş kilidini devre dışı bırak"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Uygulamaların tuş kilidini ve ilgili şifreli güvenlik önlemini devre dışı bırakmasına izin verir. Bunun geçerli bir örneği gelen bir çağrı alındığında tuş kilidinin devre dışı bırakılması, sonra çağrı bittiğinde kilidin yeniden devreye sokulmasıdır."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını oku"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Bir uygulamanın önbellek dosya sisteminde okuma yazma yapmasına izin verir."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"İnternet çağrılar yap/alma"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Uygulamanın İnternet çağ yapmak/almak için SIP hiz kullanmasına izin verir."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri kontrol edin"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Ekran kilitleme şifresinin hangi sıklıkla değiştirilmesi gerektiğini denetleyin"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Deplm şifrelemesini ayarla"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Depolanan uygulama verisinin şifrelenmiş olmasını gerektir"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Ev"</item>
<item msgid="869923650527136615">"Mobil"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"İş"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Diğer"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"PIN kodunu gir"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"PUK kodunu ve yeni PIN kodunu girin"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kodu"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Yeni PIN Kodu"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Şifre girmek için dokunun"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Kilidi açmak için şifreyi girin"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Kilidi açmak için PIN\'i girin"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonda SIM kart yok."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Lütfen SIM kart takın."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Yalnızca acil çağrılar için"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Ağ kilitli"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kart PUK kilidi devrede."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"USB depolama birimini açarsanız, kullanmakta olduğunuz bazı uygulamalar durur ve USB depolama birimi kapatılıncaya kadar kullanılamayabilir."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB işlemi başarısız oldu"</string>
<string name="dlg_ok" msgid="7376953167039865701">"Tamam"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB\'yi biçimlendir"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartı biçimlendir"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"USB depolama birimi biçimlendirilsin mi? Depolama biriminde saklanan tüm dosyalar silinir. İşlem geri alınamaz!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Katman 2 Tünel Protokolü"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN temelli önceden paylaşılmış anahtar"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN temelli sertifika"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Seçili dosya yok"</string>
<string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Dahili Depolama"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD Kart"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB depolama birimi"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Düzenle..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Güvenlik sertifikası"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Bu sertifika geçerli."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Alıcı:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Ortak ad:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Kuruluş:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Kuruluş birimi:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Yayınlayan:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Geçerlilik:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Yayınlanma tarihi:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Sona erme tarihi:"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 07b11f7..02636af 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Введений PUK неправильний."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Введені PIN-коди не збігаються."</string>
<string name="invalidPin" msgid="3850018445187475377">"Введіть PIN, який скл. з 4-8 цифр."</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="ClipMmi" msgid="6952821216480289285">"Вхідн. ід. абонента"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим польоту"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим польоту ВВІМК."</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим польоту ВИМК."</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Служби, які потребують оплати"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Дозволяє програмі отримувати та обробляти SMS повідомл. Шкідливі програми можуть відслідковувати ваші повідомлення чи видаляти їх без вашого відома."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"отримув. MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Дозволяє програмі отримувати та обробляти MMS повідомл. Шкідливі програми можуть відслідковувати ваші повідомлення чи видаляти їх без вашого відома."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"отримувати повідомлення екстрених служб"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Дозволяє програмі отримувати й обробляти повідомлення екстрених служб. Цей дозвіл доступний лише для системних програм."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"надсил. SMS повідом."</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Дозволяє програмі надсил. SMS повідомл. Шкідливі програми можуть спричин. збитки, надсилаючи повідомлення без вашого підтвердження."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"читати SMS або MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Дозволяє програмі примусово закривати будь-яку активну дію та повертатися назад. Ніколи не потрібний для звичайних програм."</string>
<string name="permlab_dump" msgid="1681799862438954752">"отрим. дані про внутр. стан сист."</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Дозволяє програмі отримувати дані про внутрішній стан системи. Шкідливі програми можуть використовувати значну кількість приватної та захищеної інформації, яка для них не призначена."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"отримувати вміст екрана"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Дозволяє програмі отримувати вміст активного вікна. Шкідливі програми можуть отримувати весь вміст вікна та вивчати весь його текст, окрім паролів."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Дозволяє власнику надсилати цілі адміністратору пристрою. Ніколи не потрібний для звичайних програм."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"змінювати орієнтацію екрана"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Дозволяє програмі будь-коли змінювати обертання екрана. Ніколи не потрібний для звичайних програм."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"змінювати швидкість указівника"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Дозволяє програмі будь-коли змінювати швидкість вказівника миші чи сенсорної панелі. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"надсилати сигнали Linux програмам"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Дозволяє програмі подавати запит щодо надсилання наданого сигналу всім постійним процесам."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"збер. програму завжди запущ."</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"запис. контактні дані"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Дозволяє програмі змінювати контактні дані (адреси), збереж. в пристрої. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Дозволяє програмі змінювати контактні дані (адресу), збереж. в телефоні. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"читати події календаря"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Дозволяє програмі зчитувати всі події календаря, збережені в пристрої. Шкідливі програми можуть використовувати це для надсилання ваших подій календаря іншим людям."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Дозволяє програмі зчитувати всі події календаря, збережені у вашому телефоні. Шкідливі програми можуть використ-ти це для надсилання подій календаря іншим людям."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"контрол. Near Field Communication"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Дозволяє прогр. обмін. даними з тегами, картками та читачами екрана Near Field Communication (NFC)."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"перехоплювати та змінювати весь мережевий трафік"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Дозволяє програмі перехоплювати та перевіряти весь мережевий трафік, наприклад, щоб установлювати з’єднання з мережею VPN. Шкідливі програми можуть контролювати, переадресовувати чи змінювати мережеві пакети без вашого відома."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Дозволяє програмі перехоплювати та перевіряти весь мережевий трафік, щоб установлювати з’єднання з мережею VPN. Шкідливі програми можуть контролювати, переадресовувати чи змінювати мережеві пакети без вашого відома."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"вимик. блок. клав."</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Дозволяє програмі вимикати блокування клавіатури та будь-який пов\'язаний захист паролем. Допустимий приклад, коли телефон вимикає блокування клавіат. при отриманні вхідного дзвінка, після завершення якого блокування клавіатури відновлюється."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"чит. налашт-ня синхр."</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Дозволяє програмі зчитувати та записувати файлову сист. кешу."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"здійсн./отрим. Інтернет-дзвін."</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Дозволяє програмі використ. службу SIP, щоб здійсн./отрим. Інтернет-дзвінки."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролює довжину паролів для розблокув. екрана та дозволені в них символи"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Контролювати частоту зміни пароля блокування екрана"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Установити шифрування носія"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Потрібно, щоб дані збереженої програми були зашифровані"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Дом."</item>
<item msgid="869923650527136615">"Мобільний"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Робоча"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Інша"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Введіть PIN-код"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Введіть PUK-код і новий PIN-код"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-код"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Новий PIN-код"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Торк. для введ. паролю"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Введіть пароль, щоб розбл."</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Введ. PIN для розблок."</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тел. немає SIM-карти."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Вставте SIM-карту."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Якщо ввімкнути носій USB, деякі програми, які викор., припинять свою роботу та можуть бути недоступними до вимкнення носія USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Помилка операції з USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматувати носій USB, видаляючи всі збережені файли? Дію не можна скасувати!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Тунельний протокол рівня 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Спільн. ключ на осн. L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN на осн. сертифіката"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
<string name="reset" msgid="2448168080964209908">"Віднов."</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Внутрішня пам’ять"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Картка SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Носій USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Редагувати..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Сертифікат безпеки"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Цей сертифікат є дійсним."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Кому видано:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Загальне ім\'я:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Організація:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Організац. підрозділ:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Ким видано:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Чинність:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Дата видачі:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Діє до:"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index cfb53ac..1b1c8ba 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"Mã PUK bạn đã nhập không chính xác."</string>
<string name="mismatchPin" msgid="3695902225843339274">"Mã PIN bạn đã nhập không khớp."</string>
<string name="invalidPin" msgid="3850018445187475377">"Nhập mã PIN có từ 4 đến 8 số."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"Nhập PUK có từ 8 số trở lên."</string>
<string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khoá PUK. Nhập mã PUK để mở khoá thẻ SIM đó."</string>
<string name="needPuk2" msgid="4526033371987193070">"Nhập mã PUK2 để bỏ chặn thẻ SIM."</string>
<string name="ClipMmi" msgid="6952821216480289285">"Số gọi đến"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Chế độ trên máy bay"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Chế độ trên máy bay BẬT"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Chế độ trên máy bay TẮT"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
<string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dịch vụ tính tiền của bạn"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"Cho phép ứng dụng nhận và xử lý tin nhắn SMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"nhận MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Các ứng dụng độc hại có thể giám sát tin nhắn của bạn hoặc xoá chúng mà không cần hiển thị tin nhắn đó cho bạn."</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"nhận các truyền phát khẩn cấp"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Cho phép ứng dụng truy xuất và xử lý các thư phát khẩn cấp. Quyền này chỉ khả dụng đối với các ứng dụng hệ thống."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"gửi tin nhắn SMS"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"Cho phép ứng dụng gửi tin nhắn SMS. Các ứng dụng độc hại có thể khiến bạn tốn tiền bằng cách gửi tin nhắn mà không cần xác nhận của bạn."</string>
<string name="permlab_readSms" msgid="4085333708122372256">"đọc SMS hoặc MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"Cho phép ứng dụng buộc bất kỳ hoạt động nào chạy trên nền đóng hoặc quay lại. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_dump" msgid="1681799862438954752">"truy xuất trạng thái bên trong của hệ thống"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"Cho phép ứng dụng truy xuất trạng thái nội bộ của hệ thống. Các ứng dụng độc hại có thể truy xuất nhiều thông tin riêng tư và bảo mật khác nhau mà thông thường không bao giờ cần đến."</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"truy xuất nội dung màn hình"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Cho phép ứng dụng truy xuất nội dung của cửa sổ hiện hành. Các ứng dụng độc hại có thể truy xuất toàn bộ nội dung cửa sổ và kiểm tra tất cả văn bản của cửa sổ ngoại trừ mật khẩu."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"tắt từng phần"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Đặt trình quản lý hoạt động sang trạng thái tắt. Không thực hiện tắt hoàn toàn."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"Cho phép chủ nhân gửi các ý định đến quản trị viên thiết bị. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"thay đổi hướng màn hình"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"Cho phép ứng dụng thay đổi việc xoay màn hình bất kỳ khi nào. Không cần thiết cho các ứng dụng thông thường."</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"thay đổi tốc độ con trỏ"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Cho phép ứng dụng thay đổi tốc độ chuột hoặc con trỏ ô di chuột vào bất kỳ lúc nào. Không bao giờ cần cho các ứng dụng thông thường."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"gửi tín hiệu Linux đến ứng dụng"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Cho phép ứng dụng yêu cầu tín hiệu đã cung cấp được gửi đến tất cả các quá trình liên tục."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"đặt ứng dụng luôn chạy"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu (địa chỉ) liên hệ được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"Đọc sự kiện lịch"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Cho phép ứng dụng đọc tất cả các sự kiện lịch được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi các sự kiện lịch của bạn cho những người khác."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Cho phép ứng dụng đọc tất cả các sự kiện lịch được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi các sự kiện lịch của bạn cho những người khác."</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"kiểm soát Liên lạc trường gần"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"Cho phép ứng dụng liên lạc với thẻ Liên lạc trường gần (NFC), thẻ và trình đọc."</string>
<string name="permlab_vpn" msgid="8345800584532175312">"chặn và sửa đổi tất cả lưu lượng truy cập mạng"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"Cho phép ứng dụng chặn và kiểm tra tất cả lưu lượng truy cập mạng, ví dụ để thiết lập kết nối VPN. Các ứng dụng độc hại có thể giám sát, chuyển hướng hoặc sửa đổi gói tin mạng mà bạn không biết."</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Cho phép ứng dụng chặn và kiểm tra tất cả lưu lượng truy cập mạng để thiết lập kết nối VPN. Các ứng dụng độc hại có thể giám sát, chuyển hướng hoặc sửa đổi gói tin mạng mà bạn không biết."</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hoá khoá phím"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hoá khoá phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hoá khoá phím khi nhận được cuộc gọi đến sau đó bật lại khoá phím khi cuộc gọi kết thúc."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hoá"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"thực hiện/nhận cuộc gọi qua Internet"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"Cho phép ứng dụng sử dụng dịch vụ SIP để thực hiện/nhận cuộc gọi qua Internet."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"Kiểm soát tần suất bắt buộc phải thay đổi mật khẩu khóa màn hình"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Đặt mã hóa dung lượng lưu trữ"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Yêu cầu dữ liệu ứng dụng được lưu trữ phải được mã hóa"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Nhà riêng"</item>
<item msgid="869923650527136615">"ĐT di động"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Cơ quan"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Khác"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Nhập mã PIN"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Nhập PUK và mã PIN mới"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Mã PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Mã Pin mới"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"Chạm để nhập mật khẩu"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khoá"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Nhập PIN để mở khóa"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Không có thẻ SIM nào trong điện thoại."</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vui lòng lắp thẻ SIM."</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Chỉ cuộc gọi khẩn cấp"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mạng đã khoá"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Thẻ SIM đã bị khoá PUK."</string>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Nếu bạn bật bộ lưu trữ USB, một số ứng dụng bạn đang sử dụng sẽ dừng và có thể không khả dụng cho tới khi bạn tắt bộ lưu trữ USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Thao tác USB không thành công"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Định dạng b.nhớ USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Định dạng thẻ SD"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Định dạng bộ nhớ USB, xóa tất cả tệp được lưu trữ tại đây? Không thể hoàn tác tác vụ!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Giao thức Đường hầm Tầng 2"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN dựa trên khoá chia sẻ trước"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN dựa trên chứng chỉ"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string>
<string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
@@ -1051,6 +1093,27 @@
<string name="storage_internal" msgid="7556050805474115618">"Bộ nhớ trong"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"Thẻ SD"</string>
<string name="storage_usb" msgid="3017954059538517278">"Bộ lưu trữ USB"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Chỉnh sửa..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
<skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
+ <string name="ssl_certificate" msgid="5226747157992111668">"Chứng chỉ bảo mật"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Chứng chỉ này hợp lệ."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Cấp cho:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Tên chung:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Tổ chức:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Đơn vị tổ chức:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Cấp bởi:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Tính hợp lệ:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Cấp vào:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Hết hạn vào:"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b45b346..18b2c06 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"您输入的 PUK 码不正确。"</string>
<string name="mismatchPin" msgid="3695902225843339274">"您输入的 PIN 码不一致。"</string>
<string name="invalidPin" msgid="3850018445187475377">"输入一个 4 至 8 位数的 PIN 码。"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"请键入至少 8 位数字的 PUK 码。"</string>
<string name="needPuk" msgid="919668385956251611">"已对 SIM 卡进行 PUK 码锁定。键入 PUK 码将其解锁。"</string>
<string name="needPuk2" msgid="4526033371987193070">"输入 PUK2 码以解锁 SIM 卡。"</string>
<string name="ClipMmi" msgid="6952821216480289285">"来电显示"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"已关闭飞行模式"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"允许应用程序接收和处理短信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。"</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"接收彩信"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"允许应用程序接收和处理彩信。恶意应用程序可借此监视您的信息,或者将信息删除而不向您显示。"</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"接收紧急广播"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"允许应用程序接收和处理紧急广播消息。此权限只适用于系统应用程序。"</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"发送短信"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"允许应用程序发送短信。恶意应用程序可能会不经您的确认就发送信息,给您带来费用。"</string>
<string name="permlab_readSms" msgid="4085333708122372256">"读取短信或彩信"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"允许应用程序强制前端的任何活动关闭并重新开始。普通应用程序从不需要使用此权限。"</string>
<string name="permlab_dump" msgid="1681799862438954752">"检索系统内部状态"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"允许应用程序检索系统的内部状态。恶意应用程序可借此检索它们本不需要的各种保密信息和安全信息。"</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"检索屏幕内容"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"允许应用程序检索活动窗口的内容。恶意应用程序可能会检索整个窗口的内容并检查其除密码外的所有文本。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用程序"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"允许持有对象将意向发送到设备管理器。普通的应用程序一律无需此权限。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"允许应用程序随时更改屏幕的旋转方向。普通应用程序从不需要使用此权限。"</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"更改指针速度"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"允许应用程序随时更改鼠标或触摸板的指针速度。普通应用程序不需要此权限。"</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"向应用程序发送 Linux 信号"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"允许应用程序请求将所提供的信号发送给所有持久进程。"</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"让应用程序始终运行"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"写入联系数据"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"允许应用程序修改您平板电脑上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。"</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"允许应用程序修改您手机上存储的联系人(地址)数据。恶意应用程序可借此清除或修改您的联系人数据。"</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"读取日历活动"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"允许应用程序读取您平板电脑上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。"</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"允许应用程序读取您手机上存储的所有日历活动。恶意应用程序可借此将您的日历活动发送给其他人。"</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"控制近距离通信"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"允许应用程序与近距离通信 (NFC) 标签、卡和读卡器进行通信。"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"拦截和修改所有网络流量"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"允许应用程序拦截和检查所有网络流量(例如建立 VPN 连接)。恶意应用程序可能会在您不知情的状况下监测、重定向或修改网络数据包。"</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"允许应用程序拦截和检查所有网络流量,以便建立 VPN 连接。恶意应用程序可能会在您不知情的状况下监测、重定向或修改网络数据包。"</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用键锁"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允许应用程序读取和写入缓存文件系统。"</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"拨打/接听互联网通话"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"允许应用程序使用 SIP 服务拨打/接听互联网通话。"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"控制屏幕解锁密码允许的长度和字符数"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"控制锁定屏幕密码的更改频率"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"需要对存储的应用程序数据进行加密"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"住宅"</item>
<item msgid="869923650527136615">"手机"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"单位"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"输入 PIN 码"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"请输入 PUK 码和新的 PIN 码"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 码"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"新的 PIN 码"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"触摸可输入密码"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"输入密码进行解锁"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"输入 PIN 进行解锁"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有 SIM 卡。"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手机中无 SIM 卡"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"请插入 SIM 卡"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您打开了 USB 存储设备,则您当前使用的某些应用程序会停止,而且在您关闭 USB 存储设备前可能都无法使用。"</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失败"</string>
<string name="dlg_ok" msgid="7376953167039865701">"确定"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"确定要格式化 USB 存储设备,清除其中存储的全部文件吗?该操作将无法撤消!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"第 2 层隧道协议"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"基于预共享密钥的 L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"基于证书的 L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"选择文件"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string>
<string name="reset" msgid="2448168080964209908">"重置"</string>
@@ -1051,6 +1093,17 @@
<string name="storage_internal" msgid="7556050805474115618">"内存空间"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB 存储器"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"编辑..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
<skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 399a5b0..6bbf019 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -46,6 +46,7 @@
<string name="badPuk" msgid="5702522162746042460">"您輸入的 PUK 不正確。"</string>
<string name="mismatchPin" msgid="3695902225843339274">"您輸入的 PIN 不符合。"</string>
<string name="invalidPin" msgid="3850018445187475377">"輸入 4~8 個數字的 PIN。"</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"輸入 8 位數以上的 PUK。"</string>
<string name="needPuk" msgid="919668385956251611">"SIM 卡的 PUK 已鎖定。請輸入 PUK 碼解除鎖定。"</string>
<string name="needPuk2" msgid="4526033371987193070">"請輸入 PUK2 以解鎖 SIM 卡。"</string>
<string name="ClipMmi" msgid="6952821216480289285">"來電顯示"</string>
@@ -151,7 +152,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛航模式"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛航模式為 [關閉]"</string>
- <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100+"</string>
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要額外費用的服務。"</string>
@@ -190,6 +191,8 @@
<string name="permdesc_receiveSms" msgid="6298292335965966117">"允許應用程式接收、處理 SMS 簡訊。請注意:惡意程式可能使用此功能監控簡訊或在您讀取前擅自刪除。"</string>
<string name="permlab_receiveMms" msgid="8894700916188083287">"接收 MMS"</string>
<string name="permdesc_receiveMms" msgid="4563346832000174373">"允許應用程式接收、處理 MMS 簡訊。請注意:惡意程式可能使用此功能監控簡訊或在您讀取前擅自刪除。"</string>
+ <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"接收緊急廣播"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"允許應用程式接收並處理緊急廣播訊息,只有系統應用程式可以具備這項權限。"</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"傳送 SMS 簡訊"</string>
<string name="permdesc_sendSms" msgid="1946540351763502120">"允許應用程式傳送 SMS 簡訊。請注意:惡意程式可能會擅自傳送簡訊,增加您的支出。"</string>
<string name="permlab_readSms" msgid="4085333708122372256">"讀取 SMS 或 MMS"</string>
@@ -220,6 +223,8 @@
<string name="permdesc_forceBack" msgid="6534109744159919013">"允許應用程式強制關閉在前端運作的活動並返回。一般應用程式不需要此功能。"</string>
<string name="permlab_dump" msgid="1681799862438954752">"接收系統內部狀態"</string>
<string name="permdesc_dump" msgid="2198776174276275220">"允許應用程式取得系統內部狀態。請注意:惡意程式可能利用此功能,不當取得私人或安全性資料。"</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"擷取螢幕內容"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"允許應用程式擷取使用中的視窗內容。請注意,惡意應用程式可藉此擷取所有視窗內容,並查看密碼之外的所有文字內容。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
@@ -265,10 +270,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"允許應用程式將調用請求 (intent) 傳送至裝置管理員;一般應用程式不需使用此選項。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"變更螢幕顯示方向"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"允許應用程式可隨時變更螢幕旋轉方向。一般應用不應使用這項功能。"</string>
- <!-- no translation found for permlab_setPointerSpeed (9175371613322562934) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"變更指標速度"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"允許應用程式可以隨時變更滑鼠或觸控板指標的移動速度,一般應用程式不需使用這個選項。"</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"傳送 Linux 訊號到應用程式"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"允許應用程式要求將支援的訊號傳送到所有持續的程序。"</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"設定應用程式持續執行"</string>
@@ -316,6 +319,14 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"輸入聯絡人資料"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"允許應用程式修改平板電腦上儲存的聯絡人 (地址) 資料。惡意應用程式可藉此清除或修改您的聯絡人資料。"</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"允許應用程式更改聯絡資訊 (地址)。請注意:惡意程式可能利用此功能,清除或修改聯絡資料。"</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"讀取日曆活動"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"允許應用程式讀取平板電腦上儲存的所有日曆活動。惡意應用程式可藉此將您的日曆活動傳送給其他人。"</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"允許應用程式讀取手機上所有日曆資料。請注意:惡意程式可能利用此功能將您的日曆資料傳送給其他人。"</string>
@@ -453,7 +464,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"控制近距離無線通訊"</string>
<string name="permdesc_nfc" msgid="9171401851954407226">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
<string name="permlab_vpn" msgid="8345800584532175312">"攔截和修改所有網路流量"</string>
- <string name="permdesc_vpn" msgid="5617893078989944219">"允許應用程式攔截和檢查所有網路流量,例如建立 VPN 連線。請注意,惡意應用程式會在您不知情的情況下,藉此監視、重新導向或修正網路套件。"</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"允許應用程式攔截和檢查所有要建立 VPN 連線的網路流量。請注意,惡意應用程式會在您不知情的情況下,藉此監視、重新導向或修改網路套件。"</string>
<string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用按鍵鎖定"</string>
<string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性。例如:收到來電時解除按鍵鎖定,通話結束後重新啟動按鍵鎖定。"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
@@ -480,6 +491,14 @@
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允許應用程式讀取及寫入快取檔案系統。"</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"撥打/接聽網路電話"</string>
<string name="permdesc_use_sip" msgid="6320376185606661843">"允許應用程式使用 SIP 服務撥打/接聽網路電話。"</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
+ <skip />
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"控制螢幕解鎖密碼所允許的長度和字元"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -498,6 +517,10 @@
<string name="policydesc_expirePassword" msgid="4844430354224822074">"控制螢幕上鎖密碼的變更頻率"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"設定儲存裝置加密"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"必須為儲存的應用程式資料加密"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
+ <skip />
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
+ <skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"住家電話"</item>
<item msgid="869923650527136615">"行動電話"</item>
@@ -612,6 +635,9 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"公司"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"輸入 PIN 碼"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"輸入 PUK 碼和新的 PIN 碼"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 碼"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"新的 Pin 碼"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7906561917570259833"><font size="17">"輕觸即可輸入密碼"</font></string>
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"輸入密碼即可解鎖"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"輸入 PIN 進行解鎖"</string>
@@ -636,6 +662,10 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"請插入 SIM 卡。"</string>
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<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>
@@ -924,6 +954,10 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"如果您開啟 USB 儲存裝置,則您正在使用的某些應用程式會停止運作,而且可能無法使用,待您將 USB 儲存裝置關閉才會恢復正常。"</string>
<string name="dlg_error_title" msgid="8048999973837339174">"USB 操作失敗"</string>
<string name="dlg_ok" msgid="7376953167039865701">"確定"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
<string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"格式化 USB 儲存裝置時,是否清除其中儲存的所有檔案?這項動作無法復原!"</string>
@@ -991,6 +1025,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"第二層通道通訊協定"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"採用預先共用金鑰的 L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"採用憑證的 L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string>
<string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1051,6 +1093,17 @@
<string name="storage_internal" msgid="7556050805474115618">"內部儲存空間"</string>
<string name="storage_sd_card" msgid="8921771478629812343">"SD 卡"</string>
<string name="storage_usb" msgid="3017954059538517278">"USB 儲存裝置"</string>
- <!-- no translation found for extract_edit_menu_button (302060189057163906) -->
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"編輯..."</string>
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
<skip />
</resources>
diff --git a/core/res/res/values-zu-rZA/arrays.xml b/core/res/res/values-zu-rZA/arrays.xml
new file mode 100644
index 0000000..5bff0f4
--- /dev/null
+++ b/core/res/res/values-zu-rZA/arrays.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_lat_lng">
+ <item>-30559482</item>
+ <item>22937506</item>
+ </integer-array>
+ <!-- Do not translate. -->
+ <integer-array name="maps_starting_zoom">
+ <item>4</item>
+ </integer-array>
+
+</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6f147e7..2a87737 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -70,6 +70,8 @@
<skip />
<!-- no translation found for invalidPin (3850018445187475377) -->
<skip />
+ <!-- no translation found for invalidPuk (8761456210898036513) -->
+ <skip />
<string name="needPuk" msgid="919668385956251611">"Ikhadi lakho le-SIM livalwe nge-PUK. Thayipha ikhodi ye-PUK ukulivula."</string>
<!-- no translation found for needPuk2 (4526033371987193070) -->
<skip />
@@ -189,16 +191,12 @@
<!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
<skip />
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Kunokususa <xliff:g id="CONTENT_TYPE">%s</xliff:g> okuningi kakhulu."</string>
- <!-- no translation found for low_memory (2292820184396262278) -->
- <skip />
- <!-- no translation found for low_memory (6632412458436461203) -->
- <skip />
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
+ <!-- outdated translation 2292820184396262278 --> <string name="low_memory" product="default" msgid="6632412458436461203">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
<!-- no translation found for me (6545696007631404292) -->
<skip />
- <!-- no translation found for power_dialog (8545351420865202853) -->
- <skip />
- <!-- no translation found for power_dialog (1319919075463988638) -->
- <skip />
+ <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Okukhethwa kukho kwethebhulethi"</string>
+ <!-- outdated translation 8545351420865202853 --> <string name="power_dialog" product="default" msgid="1319919075463988638">"Okukhethwa kukho kwethebhulethi"</string>
<!-- no translation found for silent_mode (7167703389802618663) -->
<skip />
<!-- no translation found for turn_on_radio (3912793092339962371) -->
@@ -211,19 +209,14 @@
<skip />
<!-- no translation found for shutdown_progress (2281079257329981203) -->
<skip />
- <!-- no translation found for shutdown_confirm (3385745179555731470) -->
- <skip />
- <!-- no translation found for shutdown_confirm (649792175242821353) -->
- <skip />
- <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
- <skip />
+ <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ithebhulethi yakho izocima."</string>
+ <!-- outdated translation 3385745179555731470 --> <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ithebhulethi yakho izocima."</string>
+ <string name="shutdown_confirm_question" msgid="6656441286856415014">"Ungathanda ukuvala shaqa?"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Okwakamuva"</string>
<!-- no translation found for no_recent_tasks (279702952298056674) -->
<skip />
- <!-- no translation found for global_actions (408477140088053665) -->
- <skip />
- <!-- no translation found for global_actions (2406416831541615258) -->
- <skip />
+ <string name="global_actions" product="tablet" msgid="408477140088053665">"Okukhethwa konke kwethebhulethi"</string>
+ <!-- outdated translation 408477140088053665 --> <string name="global_actions" product="default" msgid="2406416831541615258">"Okukhethwa konke kwethebhulethi"</string>
<!-- no translation found for global_action_lock (2844945191792119712) -->
<skip />
<!-- no translation found for global_action_power_off (4471879440839879722) -->
@@ -237,8 +230,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Imodi yendiza"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Imodi yendiza IVULIWE"</string>
<string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Imodi yendiza IVALIWE"</string>
- <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
- <skip />
+ <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
<!-- no translation found for safeMode (2788228061547930246) -->
<skip />
<string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
@@ -250,7 +242,7 @@
<string name="permgroupdesc_messages" msgid="7045736972019211994">"Funda futhi ubale i-SMS yakho, i-imeyili, neminye imiyalezo."</string>
<!-- no translation found for permgrouplab_personalInfo (3519163141070533474) -->
<skip />
- <!-- outdated translation 5488050357388806068 --> <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ukufinyelela okuqondile othintana nabo nekhalenda egcinwe efonini yakho."</string>
+ <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Ukufinyelela okuqondile othintana nabo nekhalenda egcinwe kwithebhulethi yakho."</string>
<string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Ukufinyelela okuqondile othintana nabo nekhalenda egcinwe efonini yakho."</string>
<!-- no translation found for permgrouplab_location (635149742436692049) -->
<skip />
@@ -274,7 +266,7 @@
<skip />
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Izici zidingeka kuphela konjiniyela bohlelo lokusebenza."</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Ukugcina"</string>
- <!-- outdated translation 9203302214915355774 --> <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela ikhadi le-SD."</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kukugcina nge-USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Finyelela ikhadi le-SD."</string>
<!-- no translation found for permlab_statusBar (7417192629601890791) -->
<skip />
@@ -293,16 +285,20 @@
<!-- no translation found for permlab_receiveMms (8894700916188083287) -->
<skip />
<string name="permdesc_receiveMms" msgid="4563346832000174373">"Ivumela uhlelo lokusebenza ukuthola nokwenza imiyalezo ye-MMS. Izinhlelo ezinonya zingase zigade imiyalezo yakho noma ziyisuse ngaphandle kokukubonisa yona."</string>
+ <!-- no translation found for permlab_receiveEmergencyBroadcast (1803477660846288089) -->
+ <skip />
+ <!-- no translation found for permdesc_receiveEmergencyBroadcast (7118393393716546131) -->
+ <skip />
<!-- no translation found for permlab_sendSms (5600830612147671529) -->
<skip />
<string name="permdesc_sendSms" msgid="1946540351763502120">"Ivumela uhlelo lokusebenza ukuthumela imiyalezo ye-SMS. Izinhlelo zokusebenza ezinonya zingakubiza imali ngokukuthumela imiyalezo ngaphandle kwesiqinisekiso."</string>
<!-- no translation found for permlab_readSms (4085333708122372256) -->
<skip />
- <!-- outdated translation 3002170087197294591 --> <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ivumela uhlelo lokusebena ukufunda imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zifunde imiyalezo eyimfihlo."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ivumela uhlelo lokusebena ukufunda imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezi-malicious zingase zifunde imiyalezo eyimfihlo."</string>
<string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ivumela uhlelo lokusebena ukufunda imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zifunde imiyalezo eyimfihlo."</string>
<!-- no translation found for permlab_writeSms (6881122575154940744) -->
<skip />
- <!-- outdated translation 6299398896177548095 --> <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe kwithebhulethi yakho noma ekhadini le-SIM. Izinhlelo ezi-malicious zingase zisuse imiyalezo yakho."</string>
<string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Ivumela uhlelo lokusebenza ukubhala imiyalezo ye-SMS egcinwe efonini yakho noma ekhadini le-SIM. Izinhlelo ezinonya zingase zisuse imiyalezo yakho."</string>
<!-- no translation found for permlab_receiveWapPush (8258226427716551388) -->
<skip />
@@ -335,13 +331,17 @@
<!-- no translation found for permlab_dump (1681799862438954752) -->
<skip />
<string name="permdesc_dump" msgid="2198776174276275220">"Ivumela uhlelo lokusebenza ukuthola isimo sangaphakathi sohlelo. Izinhlelo zokusebenza ezinonya zingase zithole ukwaziswa okwehlukahlukene okuyimfihlo noma okuphephile lokho ngokuvamile ezingeke zikudinge."</string>
+ <!-- no translation found for permlab_retrieve_window_content (8022588608994589938) -->
+ <skip />
+ <!-- no translation found for permdesc_retrieve_window_content (3390962289797156152) -->
+ <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
<string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Igwema umsebenzisi ukuba ashintshele kolunye uhlelo lokusebenza."</string>
<!-- no translation found for permlab_runSetActivityWatcher (7811586187574696296) -->
<skip />
- <!-- outdated translation 3228701938345388092 --> <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezinonya zingase zonakalise ngokuphelele uhlelo. Lemvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string>
+ <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ivumela uhlelo lokusebenza ukugada nokulawula indlela uhlelo oluqalisa ngayo imisebenzi. Izinhlelo ezi-malicious zingase zonakalise ngokuphelele uhlelo. Le mvume idingeka kuphela ekuthuthukiseni, hayi ekusebenziseni ifoni okuvamile."</string>
<!-- no translation found for permlab_broadcastPackageRemoved (2576333434893532475) -->
<skip />
<string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ivumela uhlelo lokusebenza ukusakaza isaziso sokuthi iphakheji yohlelo lokusebenza ikhishiwe. Izinhlelo ezinonya zingasebenzisa lokhu ukubulala olunye uhlelo lokusebenza olusebenzayo."</string>
@@ -369,7 +369,7 @@
<string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ivumela ukwenziwa kwemawindi ehloselwe ukusebenziswa uxhumano lomsebenzisi wohlelo lwangaphakathi. Ayisebenziswa izinhlelo zokusebenza ezivamile"</string>
<!-- no translation found for permlab_systemAlertWindow (3372321942941168324) -->
<skip />
- <!-- outdated translation 5109622689323490558 --> <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezinonya zingase zithathe isikrini sonke sefoni."</string>
+ <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ivumela uhlelo lokusebenza ukubonisa amawindi okuxwayisa ohlelo. Izinhlelo zokusebenza ezi-malicious zingase zithathe isikrini sonke."</string>
<!-- no translation found for permlab_setAnimationScale (2805103241153907174) -->
<skip />
<string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ivumela uhlelo lokusebenza ukushintsha isivinini sokugqwayiza jikelele (ukugqwayiza okusheshayo noma okulengayo) nganoma isiphi isikhathi."</string>
@@ -378,7 +378,7 @@
<string name="permdesc_manageAppTokens" msgid="977127907524195988">"Ivumela izinhlelo zokusebenza ukwenza nokuphatha amathokhini awo, ngokudlula ukuhleleka kuka-Z. Akusoze kwadingeka ezinhlelweni ezivamile."</string>
<!-- no translation found for permlab_injectEvents (1378746584023586600) -->
<skip />
- <!-- outdated translation 3946098050410874715 --> <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebeza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ifoni."</string>
+ <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebenza. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthatha ithebhulethi."</string>
<string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ivumela uhlelo lokusebenza ukuthumela izenzakalo zawo zokufakwayo (ukucindezela ukhiye, nokunye) kwezinye izihlelo zokusebeza. Izinhlelo ezinonya zingasebenzisa lokhu ukuthatha ifoni."</string>
<!-- no translation found for permlab_readInputState (469428900041249234) -->
<skip />
@@ -422,20 +422,20 @@
<string name="permdesc_installPackages" msgid="526669220850066132">"Ivumela uhlelo lokusebenza ukufaka amaphakheji amasha noma abuyekeziwe. Izinhlelo ezinonya zingasebenzisa lokhu ukufaka izinhelo zokusebenza ezintsha ngezimvume zomthetho onamandla."</string>
<!-- no translation found for permlab_clearAppCache (4747698311163766540) -->
<skip />
- <!-- outdated translation 7740465694193671402 --> <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ivumela uhlelo lokusebenza ukukhulula ukugcina kwefoni ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yohlelo."</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ivumela uhlelo lokusebenza ukukhulula ukugcina kwethebhulethii ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yohlelo."</string>
<string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ivumela uhlelo lokusebenza ukukhulula ukugcina kwefoni ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yohlelo."</string>
<string name="permlab_movePackage" msgid="728454979946503926">"Hambisa izinsiza zohlelo lokusebenza"</string>
<string name="permdesc_movePackage" msgid="6323049291923925277">"Ivumela uhlelo lokusebenza ukukhipha izinsiza zohlelo lokusebenza kwimidiya yangaphakathi iziyisa kweyangaphandle nangokuguquka."</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"funda idatha yefayela lokungena ebucayi"</string>
- <!-- outdated translation 8896449437464867766 --> <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ivumela uhlelo lokusebenza ukufunda kumafayela okungena ahlukene esistimu. Lokhu kuvumela ukuthola ukwaziswa okuvamile mayelana nokuthi wenzani ngefoni, kuhlanganise ukwaziswa komuntu siqu noma kwangasese."</string>
+ <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ivumela uhlelo lokusebenza ukufunda umafayela okungena ohlelo oluhlukene. Lokhu kuvumela ukuthola ukwaziswa okuvamile mayelana nokuthi wenzani ngethebhulethi, kodwa akumele kuqukethe ukwaziswa komuntu siqu noma okuyimfihlo."</string>
<string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ivumela uhlelo lokusebenza ukufunda kumafayela okungena ahlukene esistimu. Lokhu kuvumela ukuthola ukwaziswa okuvamile mayelana nokuthi wenzani ngefoni, kuhlanganise ukwaziswa komuntu siqu noma kwangasese."</string>
<!-- no translation found for permlab_diagnostic (8076743953908000342) -->
<skip />
<string name="permdesc_diagnostic" msgid="3121238373951637049">"Ivumela uhlolo lokusebenza ukufunda nokubhala kunoma yimuphi umthombo weqembu ledayegi; ngokwesibonle, amafayela akwi/dev. Lokhu kungase kuthinte kakhulu ukuba nokuphepha kohlelo. Lokhu kumele kusebenziselwe KUPHELA ukuhlola ihadiwe okucacile ngumkhiqizi noma u-opheretha."</string>
<!-- no translation found for permlab_changeComponentState (79425198834329406) -->
<skip />
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile efoni. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
- <!-- outdated translation 4569107043246700630 --> <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvimbela amakhono abalulekile efoni. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
+ <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
+ <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ivumela uhlelo lokusebenza ukushintsha ukuba ingabe ingxenye yolunye uhlelo lokusebenza ivuliwe noma cha. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukuvimbela amakhono abalulekile ethebhulethi. Ukunakekela kumele kusetshenziswe ngemvume, njengoba kungenzeka ukuthola izingxenye zohlelo lokusebenza kusimo esingasebenziseki, esingefani, noma esingahlaliseki."</string>
<!-- no translation found for permlab_setPreferredApplications (3393305202145172005) -->
<skip />
<string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ivumela uhlelo lokusebenza ukuguqula izinhlelo zakho ezikhethwayo. Lokhu kungavumela izinhlelo ezinonya ukushintsha ngokuthulile izinhlelo zokusebenza ezisebenziswayo, ukushintsha izinhlelo zakho zokusebenza ezikhona kakade ukuqoqa idatha yangasese kuwe."</string>
@@ -449,22 +449,30 @@
<string name="permdesc_writeGservices" msgid="6602362746516676175">"Ivumela uhlelo lokusebenza ukuguqula imephu yezinsizakalo ze-Google. Ayisebenziswa izinhlelo zokusebenza ezivamile."</string>
<!-- no translation found for permlab_receiveBootCompleted (7776779842866993377) -->
<skip />
- <!-- outdated translation 698336728415008796 --> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ivumela uhlelo lokusebenza ukuba luziqalele ngokushesha nje emva kokuba uhlelo luqede ukuqala. Lokhu kungenza kuthathe isikhathi ukuqalisa ifoni futhi kuvumele uhlelo lokusebenza ukwehlisa ifoni yonke ngokusebenza njalo."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ivumela uhlelo lokusebenza ukuba luziqalele ngokushesha nje emva kokuba uhlelo luqede ukuqala. Lokhu kungenza kuthathe isikhathi ukuqalisa ithebhulethi futhi kuvumele uhlelo lokusebenza ukwehlisa ithebhulethi yonke ngokusebenza njalo."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ivumela uhlelo lokusebenza ukuba luziqalele ngokushesha nje emva kokuba uhlelo luqede ukuqala. Lokhu kungenza kuthathe isikhathi ukuqalisa ifoni futhi kuvumele uhlelo lokusebenza ukwehlisa ifoni yonke ngokusebenza njalo."</string>
<!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
<skip />
- <!-- outdated translation 1920045289234052219 --> <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezi-malicious zingenza ithebhulethii ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingahlaliseki ngokuyibangela ukuba isebenzise inkumbulo eningi kakhulu."</string>
<!-- no translation found for permlab_readContacts (6219652189510218240) -->
<skip />
- <!-- outdated translation 3371591512896545975 --> <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo zokusebenza zonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
<string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo zokusebenza zonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
<!-- no translation found for permlab_writeContacts (644616215860933284) -->
<skip />
- <!-- outdated translation 3924383579108183601 --> <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo ezi-malicious zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
<string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ivumela uhlelo lokusebenza ukuguqula idatha yothintana naye (ikheli) egcinwe efonini yakho. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula idatha yakho yothintana naye."</string>
+ <!-- no translation found for permlab_readProfile (2211941946684590103) -->
+ <skip />
+ <!-- no translation found for permdesc_readProfile (4732942280141331352) -->
+ <skip />
+ <!-- no translation found for permlab_writeProfile (6561668046361989220) -->
+ <skip />
+ <!-- no translation found for permdesc_writeProfile (8040643023682531996) -->
+ <skip />
<string name="permlab_readCalendar" msgid="6898987798303840534">"funda izenzakalo zekhalenda"</string>
- <!-- outdated translation 5533029139652095734 --> <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
+ <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
<string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ivumela uhlelo lokusebenza ukufunda zonke izenzakalo zekhalenda ezigcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela izenzakalo zakho zekhalenda kwabanye abantu."</string>
<string name="permlab_writeCalendar" msgid="3894879352594904361">"Yengeza noma guqula izenzakalo zekhalenda bese uthumelela izivakashi i-imeyli"</string>
<string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ivumela uhlelo lokusebenza ukufaka noma ukushintsha izenzakalo ekhalendeni yakho, okungase kuthumele i-imeyli kubavakashi. Izinhlelo ezinonya zingase zisebenzise lokhu ukusula noma ukuguqula izenzakalo zekhalenda noma ukuthumela abavakashi i-imeyli."</string>
@@ -478,11 +486,11 @@
<string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Yenza imithombo yokudlala ukuhlola. Izinhlelo ezinonya zingase zisebenzise lokhu ukukhipha indawo futhi/noma isimo esibuyiswe imithombo yendawo yangempela njenge-GPS noma abahlinzeki Benethiwekhi noma zigade futhi zibike indawo yakho njengomthombo wangaphandle."</string>
<!-- no translation found for permlab_accessFineLocation (8116127007541369477) -->
<skip />
- <!-- outdated translation 7411213317434337331 --> <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kumithombo ecocekile Njegesistimu Yokumisa Jikelele efonini, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
+ <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Finyelela kwimithombo ecocekile Njegesistimu Yokumisa Jikelele kwithebhulethi, lapho itholakala. Izinhlelo ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
<string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Finyelela kumithombo ecocekile Njegesistimu Yokumisa Jikelele efonini, lapho itholakala. Izinhlelo ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi, futhi ingadonsa amandla angeziwe ebhetri."</string>
<!-- no translation found for permlab_accessCoarseLocation (4642255009181975828) -->
<skip />
- <!-- outdated translation 8235655958070862293 --> <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela kundawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola indawo elungile yefoni, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
+ <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Finyelela indawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola endaweni elungile yethebhulethi, lapho itholakala khona. Izinhlelo zokusebenza ezi-malicious zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
<string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Finyelela kundawo yamaholohola njengesizinda semininingwane somakhalekhukhwini ukuthola indawo elungile yefoni, lapho itholakala khona. Izinhlelo zokusebenza ezinonya zingasebenzisa lokhu ukuthola ukuthi ukuphi."</string>
<!-- no translation found for permlab_accessSurfaceFlinger (2363969641792388947) -->
<skip />
@@ -498,33 +506,29 @@
<string name="permdesc_recordAudio" msgid="6493228261176552356">"Ivumela uhlelo lokusebenza ukufinyelela indlela yokurekhoda umsindo."</string>
<string name="permlab_camera" msgid="3616391919559751192">"thatha izithombe namavidiyo"</string>
<string name="permdesc_camera" msgid="6004878235852154239">"Ivumela uhlelo lokusebenza ukuthatha izithombe ngekhamera. Lokhu kuvumela uhlelo lokusebenza nganoma isiphi isikhathi ukuqoqa imifanekiso leyo ikhamera ezibonayo."</string>
- <!-- no translation found for permlab_brick (2961292205764488304) -->
- <skip />
- <!-- no translation found for permlab_brick (8337817093326370537) -->
- <skip />
- <!-- outdated translation 5569526552607599221 --> <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ivumela uhlelo lokusebenza ukuvimbela yonke ifoni ngokuphelele. Lokhu kuyingozi kakhulu."</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vimbela ngokuphelele ithebhulethi"</string>
+ <!-- outdated translation 2961292205764488304 --> <string name="permlab_brick" product="default" msgid="8337817093326370537">"vimbela ngokuphelele ithebhulethi"</string>
+ <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ivumela uhlelo lokusebenza ukuvimbela yonke ithebhulethi ngokuphelele. Lokhu kuyingozi kakhulu."</string>
<string name="permdesc_brick" product="default" msgid="5569526552607599221">"Ivumela uhlelo lokusebenza ukuvimbela yonke ifoni ngokuphelele. Lokhu kuyingozi kakhulu."</string>
- <!-- no translation found for permlab_reboot (3436634972561795002) -->
- <skip />
- <!-- no translation found for permlab_reboot (2898560872462638242) -->
- <skip />
- <!-- outdated translation 7914933292815491782 --> <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ivumela uhlelo lokusebenza ukuphoqelela ifoni ukuqalisa phansi."</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"phoqelela ukuqalisa phansi ithebhulethi"</string>
+ <!-- outdated translation 3436634972561795002 --> <string name="permlab_reboot" product="default" msgid="2898560872462638242">"phoqelela ukuqalisa phansi ithebhulethi"</string>
+ <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ivumela uhlelo lokusebenza ukuphoqelela ithebhulethi ukuqalisa phansi."</string>
<string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Ivumela uhlelo lokusebenza ukuphoqelela ifoni ukuqalisa phansi."</string>
<!-- no translation found for permlab_mount_unmount_filesystems (1761023272170956541) -->
<skip />
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ivumela izinhlelo ukukhweza nokukwehlisa izinhlelo zefayela zokugcina okukhiphekayo."</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"fometha ukugcina kwangaphandle"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ivumela uhlelo lokusebenza ukufometha ukugcina okukhiphekayo."</string>
- <!-- outdated translation 1070364079249834666 --> <string name="permlab_asec_access" msgid="3411338632002193846">"thola ukwaziswa ngokugcina okuphephile"</string>
- <!-- outdated translation 7691616292170590244 --> <string name="permdesc_asec_access" msgid="8820326551687285439">"Ivumela uhlelo lokusebenza ukuthola ukwaziswa ekugcineni okuphephile."</string>
- <!-- outdated translation 7312078032326928899 --> <string name="permlab_asec_create" msgid="6414757234789336327">"yenza ukusesha okuphephile"</string>
- <!-- outdated translation 7041802322759014035 --> <string name="permdesc_asec_create" msgid="2621346764995731250">"Ivumela uhlelo lokusebenza ukwenza ukugcina okuphephile."</string>
- <!-- outdated translation 7787322878955261006 --> <string name="permlab_asec_destroy" msgid="526928328301618022">"yonakalisa ukugcina okuphephile"</string>
- <!-- outdated translation 5740754114967893169 --> <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ivumela uhlelo lokusebenza ukonakalisa ukugcina okuphephile."</string>
- <!-- outdated translation 7517449694667828592 --> <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"khuphula / yehlisa ukugcina okuphephile"</string>
- <!-- outdated translation 5438078121718738625 --> <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ivumela uhlelo lokusebenza ukukhweza / ukwehlisa ukugcina okuphephile."</string>
- <!-- outdated translation 5685344390439934495 --> <string name="permlab_asec_rename" msgid="7496633954080472417">"qamba kabusha ukugcina okuphephile"</string>
- <!-- outdated translation 1387881770708872470 --> <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ivumela uhlelo lokusebenza ukuqamba kabusha ukugcina okuphephile."</string>
+ <string name="permlab_asec_access" msgid="3411338632002193846">"thola ukwaziswa ekugcineni kwangaphakathi"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Ivumela uhlelo lokusebenza ukuthola ukwaziswa ekugcineni kwangaphakathi."</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"dala ukugcina kwangaphakathi"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Ivumela uhlelo lokusebenza ukwenza ukugcina kwangaphakathi."</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"yonakalisa ukugcina kwanaphakathi"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ivumela uhlelo lokusebenza ukonakalisa ukugcina kwangaphakathi."</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"khweza / yehlisa ukugcina kwangaphakathi"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ivumela uhlelo lokusebenza ukukhuphula / ukwehlisa ukugcina kwangaphakathi."</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"qamba kabusha ukugcina kwangaphakathi"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ivumela uhlelo lokusebenza ukuqamba kabusha ukugcina kwangaphakathi."</string>
<!-- no translation found for permlab_vibrate (7768356019980849603) -->
<skip />
<string name="permdesc_vibrate" msgid="2886677177257789187">"Ivumela uhlelo lokusebenza ukulawula isidlidlizi."</string>
@@ -535,10 +539,8 @@
<skip />
<!-- no translation found for permdesc_manageUsb (6148489202092166164) -->
<skip />
- <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
- <skip />
- <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
- <skip />
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"sebenzisa imithetho elandelwayo ye-MTP"</string>
+ <string name="permdesc_accessMtp" msgid="6532961200486791570">"Ivumela ukufinyelela umshayeli we-kernel MTP ukusebenzisa umthetho olandelwayo we-MTP USB"</string>
<!-- no translation found for permlab_hardware_test (4148290860400659146) -->
<skip />
<string name="permdesc_hardware_test" msgid="3668894686500081699">"Ivumela uhlelo lokusebenza ukulawula okuphathelene nomngcele ngenjongo yokuhlola ihadiwe."</string>
@@ -548,7 +550,7 @@
<!-- no translation found for permlab_callPrivileged (4198349211108497879) -->
<skip />
<string name="permdesc_callPrivileged" msgid="244405067160028452">"Ivumela uhlelo lokusebenza ukushayela noma iyiphi inombolo yocingo, kuhlanganise izinombolo eziphuthumayo, ngaphandle kokungenela kwakho. Izinhlelo zokusebenza ezinonya zingase zenze izincingo ezingadingeki nezingekho ezimthethweni kwizinsizakalo eziphuthumayo."</string>
- <!-- outdated translation 5604848095315421425 --> <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukuhlela ifoni nge-CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukuhlela ithebhulethi nge-CDMA"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukuhlela ifoni nge-CDMA"</string>
<string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Ivumela uhlelo lokusebenza ukuqalisa amalungiselelo e-CDMA. Izinhlelo ezinonya ngokungadingekile zingaqalisa amalungiselelo e-CDMA."</string>
<!-- no translation found for permlab_locationUpdates (7785408253364335740) -->
@@ -564,21 +566,17 @@
<string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ivumela uhlelo lokusebenza ukulawula izici zefoni zedivaysi. Uhlelo lokusebenza olunalemvume lungashintsha amanethiwekhi, luvule futhi luvale umsakazo wefoni futhi ngaphandle kokukwazisa."</string>
<string name="permlab_readPhoneState" msgid="2326172951448691631">"funda isimo sefoni nokuhlonza"</string>
<string name="permdesc_readPhoneState" msgid="188877305147626781">"Ivumela uhlelo lokusebenza ukufinyelela izici zefoni zedivaysi. Uhlelo lokusebenza olunemvume lungathola inombolo yocingo nenombolo yomkhiqizo yalefoni, kungaba ukuthi ucingo luyasebenza, inombolo leyo ucingo oluxhume kuyo ngisho nokufanayo."</string>
- <!-- no translation found for permlab_wakeLock (1531731435011495015) -->
- <skip />
- <!-- no translation found for permlab_wakeLock (573480187941496130) -->
- <skip />
- <!-- outdated translation 7584036471227467099 --> <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ivumela uhlelo lokusebenza ukugwema ifoni ukuba ingalali."</string>
+ <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"gwema ithebhulethi ukuba ingalali"</string>
+ <!-- outdated translation 1531731435011495015 --> <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"gwema ithebhulethi ukuba ingalali"</string>
+ <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ivumela uhlelo lokusebenza ukugwema ithebhulethi ukuthi ingalali."</string>
<string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Ivumela uhlelo lokusebenza ukugwema ifoni ukuba ingalali."</string>
- <!-- no translation found for permlab_devicePower (2787034722616350417) -->
- <skip />
- <!-- no translation found for permlab_devicePower (4928622470980943206) -->
- <skip />
- <!-- outdated translation 4577331933252444818 --> <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ivumela uhlelo lokusebenza ukuvula noma ukuvala ifoni."</string>
+ <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"amandla efoni avuliwe noma avaliwe"</string>
+ <!-- outdated translation 2787034722616350417 --> <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"amandla efoni avuliwe noma avaliwe"</string>
+ <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ivumela uhlelo lokusebenza ukuvala noma ukuvula ithebhulethi."</string>
<string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Ivumela uhlelo lokusebenza ukuvula noma ukuvala ifoni."</string>
<!-- no translation found for permlab_factoryTest (3715225492696416187) -->
<skip />
- <!-- outdated translation 8136644990319244802 --> <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Sebenzise njengokuhlola komkhiqizi wezinga eliphansi, uvumela ukufinyelela okugcwele ihadiwe yefoni. Itholakala kuphela lapho ifoni isebenza kwimodi yokuhlola yomkhiqizi."</string>
+ <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Sebenzise njengokuhlola komkhiqizi wezinga eliphansi, uvumela ukufinyelela okugcwele ihadiwe yethebhulethi. Itholakala kuphela lapho ithebhulethi isebenza kwimodi yokuhlola yomkhiqizi."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Sebenzise njengokuhlola komkhiqizi wezinga eliphansi, uvumela ukufinyelela okugcwele ihadiwe yefoni. Itholakala kuphela lapho ifoni isebenza kwimodi yokuhlola yomkhiqizi."</string>
<!-- no translation found for permlab_setWallpaper (6627192333373465143) -->
<skip />
@@ -590,17 +588,17 @@
<skip />
<string name="permdesc_masterClear" msgid="5033465107545174514">"Ivumela uhlelo loksuebenza ukuhlela kabusha ngokuphelele isistimu kuzilungiselelo zalo zasembonini, ukusula yonke idatha, ukumisa, nezinhlelo zokusebenza ezifakiwe."</string>
<string name="permlab_setTime" msgid="2021614829591775646">"Hlela isikhathi"</string>
- <!-- outdated translation 667294309287080045 --> <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Ivumela uhlelo lokusebenza ukushintsha isikhathi sewashi sefoni."</string>
+ <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Ivumela uhlelo lokusebenza ukushintsha isikhathi sewashi lethebhulethi."</string>
<string name="permdesc_setTime" product="default" msgid="667294309287080045">"Ivumela uhlelo lokusebenza ukushintsha isikhathi sewashi sefoni."</string>
<!-- no translation found for permlab_setTimeZone (2945079801013077340) -->
<skip />
- <!-- outdated translation 1902540227418179364 --> <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Ivumela uhlelo lokusebenza ukushintsha umkhawulo wesikhathi wefoni."</string>
+ <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Ivumela uhlelo lokusebenza ukushintsha umkhawulo wesikhathi wethebhulethi."</string>
<string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Ivumela uhlelo lokusebenza ukushintsha umkhawulo wesikhathi wefoni."</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"yenza njenge Nsizakalo Yemeneja ye-Akhawunti"</string>
<string name="permdesc_accountManagerService" msgid="6056903274106394752">"Ivumela uhlelo lokusebenza ukwenza amakholi Kwiziqinisekisi ze-Akhawunti"</string>
<!-- no translation found for permlab_getAccounts (4549918644233460103) -->
<skip />
- <!-- outdated translation 6839262446413155394 --> <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ivumela uhlelo lokusebenza ukuthola uhlu lwama-akhawunti aziwa ifoni."</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ivumela uhlelo lokusebenza ukuthola uhlu lwama-akhawunti aziwa ithebhulethi."</string>
<string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Ivumela uhlelo lokusebenza ukuthola uhlu lwama-akhawunti aziwa ifoni."</string>
<string name="permlab_authenticateAccounts" msgid="3940505577982882450">"izenza umqinisekisi we-akhawunti"</string>
<string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Ivumela uhlelo lokusebenza ukusebenzisa amakhono okufakazela ubuqiniso e-akhawunti Emeneja ye-Akhawunti, kuhlanganise ukwenza ama-akhaeunti nokuthi ngisho nokumisa amaphasiwedi ayo."</string>
@@ -634,19 +632,17 @@
<string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ivumela uhlelo lokusebenza ukuthola amaphakhethe ngokungaqondile angeyona awedivaysi yakho. Lokhu kungaba usizo lapho uthola izinsizakalo ezinikezwa eduze. Kusebenzisa amandla amaninigi kunemodi yokungajikijeli okuningi."</string>
<!-- no translation found for permlab_bluetoothAdmin (1092209628459341292) -->
<skip />
- <!-- outdated translation 7256289774667054555 --> <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ivumela uhlelo lokusebenza ukumisa ifoni ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ivumela uhlelo lokusebenza ukumisa ithebhulethi ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Ivumela uhlelo lokusebenza ukumisa ifoni ye-Bluetooth yasendawni, nokuthola nokubhanqanisa namadivaysi okulawula okukude."</string>
<!-- no translation found for permlab_bluetooth (8361038707857018732) -->
<skip />
- <!-- outdated translation 762515380679392945 --> <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ivumela uhlelo lokusebenza ukubuka ukumisa ifoni ye-Bluetooth yasendaweni, nokwenza futhi nokwamukela uxhumano ngamadivaysi abhangqene."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ivumela uhlelo lokusebenza ukubuka ukumisa ifoni yethebhulethi ye-Bluetooth yasendaweni, nokwenza futhi nokwamukela uxhumano ngamadivaysi abhangqene."</string>
<string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ivumela uhlelo lokusebenza ukubuka ukumisa ifoni ye-Bluetooth yasendaweni, nokwenza futhi nokwamukela uxhumano ngamadivaysi abhangqene."</string>
- <!-- no translation found for permlab_nfc (4423351274757876953) -->
- <skip />
- <!-- no translation found for permdesc_nfc (9171401851954407226) -->
- <skip />
+ <string name="permlab_nfc" msgid="4423351274757876953">"lawula Uxhumano Lwenkambu Eseduze"</string>
+ <string name="permdesc_nfc" msgid="9171401851954407226">"Ivumela uhlelo lokusebenza ukuxhumana nezilengisi, amakhadi, nabafundi Bokuxhumana Nenkambu Eseduze (NFC)."</string>
<!-- no translation found for permlab_vpn (8345800584532175312) -->
<skip />
- <!-- no translation found for permdesc_vpn (5617893078989944219) -->
+ <!-- no translation found for permdesc_vpn (7093963230333602420) -->
<skip />
<!-- no translation found for permlab_disableKeyguard (4977406164311535092) -->
<skip />
@@ -671,41 +667,45 @@
<string name="permdesc_readDictionary" msgid="1082972603576360690">"Ivumela uhlelo lokusebenza ukufunda noma yimaphi amagama ayimfihlo, amagama nemisho leyo umsebenzisi ayigcine kwisichazamazwi somsebenzisi."</string>
<string name="permlab_writeDictionary" msgid="6703109511836343341">"bhala kwisichazamazwi esicacisiwe somsebenzisi"</string>
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ivumela uhlelo lokusebenza ukubhala amagama amasha kwisichazamazwi somsebenzisi."</string>
- <!-- outdated translation 8079403759001777291 --> <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe kwekhadi le-SD"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe kokugcina nge-USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"guqula/susa okuqukethwe kwekhadi le-SD"</string>
- <!-- outdated translation 6643963204976471878 --> <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala ekhadini le-SD."</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala ekugcineni nge-USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ivumela uhlelo lokusebenza ukubhala ekhadini le-SD."</string>
- <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
- <skip />
- <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
- <skip />
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"guqula/susa okuqukethwe kokugcina imidiya yangaphakathi"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ivumela uhlelo lokusebenza ukuguqula okuqukethwe kokugcina kwemidiya yangaphakathi."</string>
<string name="permlab_cache_filesystem" msgid="5656487264819669824">"finyelela kunqolobane yesistimu yefayela"</string>
<string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Ivumela uhlelo lokusebenza ukufunda nokubhala uhlelo lwesistimu lwenqolobane."</string>
- <!-- no translation found for permlab_use_sip (5986952362795870502) -->
+ <string name="permlab_use_sip" msgid="5986952362795870502">"yena/thola amakholi e-Inthanethi"</string>
+ <string name="permdesc_use_sip" msgid="6320376185606661843">"Ivumela uhlelo lokusebenza ukusebenzisa insizakalo ye-SIP ukwenza/ukuthola amakholi e-Inthanethi."</string>
+ <!-- no translation found for permlab_readNetworkUsageHistory (7862593283611493232) -->
<skip />
- <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
+ <!-- no translation found for permdesc_readNetworkUsageHistory (6040738474779135653) -->
+ <skip />
+ <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
+ <skip />
+ <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
<skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
<string name="policydesc_limitPassword" msgid="9083400080861728056">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
- <!-- outdated translation 7227578260165172673 --> <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Gada inani lamaphasiwedi angalungile afakwe lapho uvula isikrini, bese uvala ifoni noma sula yonke idatha yefoni uma aphasiwedi amaningi kakhulu angalungile efakiwe."</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Gada inani lamaphasiwedi angalungile afakiwe lapho uvula isikrini, bese uvala ithebhulethi noma sula yonke idatha yethebhulethi uma kunamaphasiwedi amaningi kakhulu angalungile afakiwe."</string>
<string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Gada inani lamaphasiwedi angalungile afakwe lapho uvula isikrini, bese uvala ifoni noma sula yonke idatha yefoni uma aphasiwedi amaningi kakhulu angalungile efakiwe."</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"Shintsha iphasiwedi yokuvula isikrini"</string>
<string name="policydesc_resetPassword" msgid="5391240616981297361">"Shintsha iphasiwedi yokuvula isikrini"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Vala isikrini"</string>
<string name="policydesc_forceLock" msgid="5696964126226028442">"Lawula ukuthi isikrini sivala kanjani futhi nini"</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Sula yonke idatha"</string>
- <!-- outdated translation 7669895333814222586 --> <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Sula idatha yefoni ngaphandle kwesixwayiso, ngokwenza ukuhlela kabusha idatha yemboni"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Sula idatha yethebhulethi ngaphandle kwesaziso, ngokwenza ukusetha kabusha kwemboni."</string>
<string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Sula idatha yefoni ngaphandle kwesixwayiso, ngokwenza ukuhlela kabusha idatha yemboni"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Misa ummelelii jikelele yedivaysi"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Misa iphrokzi jikelele yedivaysi ukusebenzisa ngenkathi inqumbomgomo ivunyelwa. Idivaysi yokuqala kuphela yokuphatha emisa ummeleli jikelele esebenzayo."</string>
- <!-- no translation found for policylab_expirePassword (885279151847254056) -->
+ <!-- outdated translation 2314569545488269564 --> <string name="policylab_expirePassword" msgid="885279151847254056">"Hlela ukuphelelwa isikhathi kwephasiwedi."</string>
+ <!-- outdated translation 7276906351852798814 --> <string name="policydesc_expirePassword" msgid="4844430354224822074">"Lawula ukuthi iphasiwedi yokuvala isikrini kumele ishintshwe nini"</string>
+ <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setha umbhalo wemfihlo wokugcina"</string>
+ <string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Idinga ukuba idatha yohlelo lokusebenza olugciniwe ibhalwe ngokufihlekileyo"</string>
+ <!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
- <!-- no translation found for policydesc_expirePassword (4844430354224822074) -->
- <skip />
- <!-- no translation found for policylab_encryptedStorage (8901326199909132915) -->
- <skip />
- <!-- no translation found for policydesc_encryptedStorage (2504984732631479399) -->
+ <!-- no translation found for policydesc_disableCamera (5680054212889413366) -->
<skip />
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Ekhaya"</item>
@@ -771,11 +771,10 @@
<string name="phoneTypeWorkPager" msgid="649938731231157056">"Isicingo Somsebenzi"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Umsizi"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"I-MMS"</string>
- <!-- no translation found for eventTypeCustom (7837586198458073404) -->
- <skip />
+ <string name="eventTypeCustom" msgid="7837586198458073404">"Ngokwezifiso"</string>
<string name="eventTypeBirthday" msgid="2813379844211390740">"Usuku lokuzalwa"</string>
<string name="eventTypeAnniversary" msgid="3876779744518284000">"Usuku olugujwa minyaka yonke"</string>
- <!-- outdated translation 5834288791948564594 --> <string name="eventTypeOther" msgid="7388178939010143077">"Isenzakalo"</string>
+ <string name="eventTypeOther" msgid="7388178939010143077">"Okunye"</string>
<string name="emailTypeCustom" msgid="8525960257804213846">"Ngokwezifiso"</string>
<string name="emailTypeHome" msgid="449227236140433919">"Ekhaya"</string>
<string name="emailTypeWork" msgid="3548058059601149973">"Umsebenzi"</string>
@@ -802,41 +801,32 @@
<string name="orgTypeWork" msgid="29268870505363872">"Umsebenzi"</string>
<string name="orgTypeOther" msgid="3951781131570124082">"Okunye"</string>
<string name="orgTypeCustom" msgid="225523415372088322">"Ngokwezifiso"</string>
- <!-- no translation found for relationTypeCustom (3542403679827297300) -->
- <skip />
- <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
- <skip />
- <!-- no translation found for relationTypeBrother (8757913506784067713) -->
- <skip />
- <!-- no translation found for relationTypeChild (1890746277276881626) -->
- <skip />
- <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
- <skip />
- <!-- no translation found for relationTypeFather (5228034687082050725) -->
- <skip />
- <!-- no translation found for relationTypeFriend (7313106762483391262) -->
- <skip />
- <!-- no translation found for relationTypeManager (6365677861610137895) -->
- <skip />
- <!-- no translation found for relationTypeMother (4578571352962758304) -->
- <skip />
- <!-- no translation found for relationTypeParent (4755635567562925226) -->
- <skip />
- <!-- no translation found for relationTypePartner (7266490285120262781) -->
- <skip />
- <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
- <skip />
- <!-- no translation found for relationTypeRelative (1799819930085610271) -->
- <skip />
- <!-- no translation found for relationTypeSister (1735983554479076481) -->
- <skip />
- <!-- no translation found for relationTypeSpouse (394136939428698117) -->
- <skip />
+ <string name="relationTypeCustom" msgid="3542403679827297300">"Ngokwezifiso"</string>
+ <string name="relationTypeAssistant" msgid="6274334825195379076">"Umsizi"</string>
+ <string name="relationTypeBrother" msgid="8757913506784067713">"Ubhuti"</string>
+ <string name="relationTypeChild" msgid="1890746277276881626">"Ingane"</string>
+ <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Umlingane Wasendaweni"</string>
+ <string name="relationTypeFather" msgid="5228034687082050725">"Ubaba"</string>
+ <string name="relationTypeFriend" msgid="7313106762483391262">"Umngane"</string>
+ <string name="relationTypeManager" msgid="6365677861610137895">"Imeneja"</string>
+ <string name="relationTypeMother" msgid="4578571352962758304">"Umama"</string>
+ <string name="relationTypeParent" msgid="4755635567562925226">"Umzali"</string>
+ <string name="relationTypePartner" msgid="7266490285120262781">"Uzakwethu"</string>
+ <string name="relationTypeReferredBy" msgid="101573059844135524">"Kusikiselwe ngu-"</string>
+ <string name="relationTypeRelative" msgid="1799819930085610271">"Isihlobo"</string>
+ <string name="relationTypeSister" msgid="1735983554479076481">"Usisi"</string>
+ <string name="relationTypeSpouse" msgid="394136939428698117">"Umlingane"</string>
<string name="sipAddressTypeCustom" msgid="2473580593111590945">"Ngokwezifiso"</string>
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Ekhaya"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Umsebenzi"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Okunye"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Faka ikhodi ye-PIN"</string>
+ <!-- no translation found for keyguard_password_enter_puk_code (5965173481572346878) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_puk_prompt (1341112146710087048) -->
+ <skip />
+ <!-- no translation found for keyguard_password_enter_pin_prompt (2987350144349051286) -->
+ <skip />
<!-- no translation found for keyguard_password_entry_touch_hint (7906561917570259833) -->
<skip />
<string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Faka iphasiwedi ukuvula"</string>
@@ -869,12 +859,14 @@
<skip />
<!-- no translation found for lockscreen_missing_sim_message_short (7381499217732227295) -->
<skip />
- <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
- <skip />
- <!-- no translation found for lockscreen_missing_sim_message (2186920585695169078) -->
- <skip />
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Alikho ikhadi le-SIM efonini."</string>
+ <!-- outdated translation 151659196095791474 --> <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Alikho ikhadi le-SIM efonini."</string>
<!-- no translation found for lockscreen_missing_sim_instructions (8874620818937719067) -->
<skip />
+ <!-- no translation found for lockscreen_missing_sim_instructions_long (7138450788301444298) -->
+ <skip />
+ <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
+ <skip />
<string name="emergency_calls_only" msgid="6733978304386365407">"Amakholi aphuthumayo kuphela"</string>
<!-- no translation found for lockscreen_network_locked_message (143389224986028501) -->
<skip />
@@ -888,8 +880,7 @@
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Udwebe ngokungalungile iphathini yakho yokuvula izikhathi ezingu- <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Sicela uzame futhi emasekhondini angu-<xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Ufake ngokungalungile iphasiwedi yakho izikhathi ezingu- <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Sicela uzame futhi emasekhondini angu- <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Ufake ngokungalungile i-PIN yakho izikhathi ezingu- <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Sicela uzame futhi emasekhondini angu- <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
- <!-- no translation found for lockscreen_failed_attempts_almost_glogin (8687762517114904651) -->
- <skip />
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Udwebe ngokungalungile iphathini yakho yokuvula izikhathi ezingu- <xliff:g id="NUMBER_0">%d</xliff:g>. Emva <xliff:g id="NUMBER_1">%d</xliff:g> kweminye imizamo engaphumelelanga, uzocelwa ukuvula ithebhulethi yakho usebenzisa ukungena ngemvume kwi-Google."\n\n" Sicela uzame futhi emasekhondini angu- <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Udwebe ngokungalungile iphathini yakho yokuvula izikhathi ezingu <xliff:g id="NUMBER_0">%d</xliff:g>. Emva <xliff:g id="NUMBER_1">%d</xliff:g>kweminye imizamo engaphumelelanga, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume e-Google."\n\n" Sicela uzame futhi emasekhondini angu- <xliff:g id="NUMBER_2">%d</xliff:g>."</string>
<!-- no translation found for lockscreen_too_many_failed_attempts_countdown (6251480343394389665) -->
<skip />
@@ -930,22 +921,16 @@
<!-- no translation found for save_password_label (6860261758665825069) -->
<skip />
<string name="double_tap_toast" msgid="1068216937244567247">"Ithiphu; thepha kabili ukusondeza ngaphandle nangaphakathi."</string>
- <!-- no translation found for autofill_this_form (1272247532604569872) -->
- <skip />
- <!-- no translation found for setup_autofill (8154593408885654044) -->
- <skip />
- <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
- <skip />
- <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
- <skip />
- <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
- <skip />
- <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
- <skip />
+ <string name="autofill_this_form" msgid="1272247532604569872">"Ukugcwalisa Okuzenzakalelayo"</string>
+ <string name="setup_autofill" msgid="8154593408885654044">"Misa Ukugcwalisa Okuzenzakalelayo"</string>
+ <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+ <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+ <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+ <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"funda umlando Wesiphequluli namabhukimakhi"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ivumela uhlelo lokusebenza ukufunda wonke ama-URL lawo Isiphequluli esiwavakashele, ngisho nawo wonke amabhukimakhi Esiphequluli."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"bhala umlando Wesiphequluli namabhukhimaki"</string>
- <!-- outdated translation 945571990357114950 --> <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezi-malicious zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ivumela izinhlelo zokusebenza ukuguqula umlando Wesiphequluli noma amabhukimakhi agcinwe efonini yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukwesula noma ukuguqula idatha yakho Yesiphequluli."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"misa i-alamu ewashini le-alamu"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Ivumela uhlelo lokusebenza ukumisa i-alamu kuhlelo lokusebenza lewashi le-alawmu elifakiwe. Ezinye izinhlelo zokusebenza zewashi le-alamu zingase zingasebenzisi lesi sici."</string>
@@ -1096,8 +1081,7 @@
<skip />
<!-- no translation found for paste (5629880836805036433) -->
<skip />
- <!-- no translation found for pasteDisabled (7259254654641456570) -->
- <skip />
+ <string name="pasteDisabled" msgid="7259254654641456570">"Ayikho into yokunamathiselwa"</string>
<!-- no translation found for copyUrl (2538211579596067402) -->
<skip />
<string name="selectTextMode" msgid="6738556348861347240">"Khetha umbhalo..."</string>
@@ -1106,10 +1090,8 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
<!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
<skip />
- <!-- no translation found for low_internal_storage_view_text (4231085657068852042) -->
- <skip />
- <!-- no translation found for low_internal_storage_view_text (635106544616378836) -->
- <skip />
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Isikhala sokugcina sethebhulethi siya ngokuphela."</string>
+ <!-- outdated translation 4231085657068852042 --> <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Isikhala sokugcina sethebhulethi siya ngokuphela."</string>
<!-- no translation found for ok (5970060430562524910) -->
<skip />
<!-- no translation found for cancel (6442560571259935130) -->
@@ -1228,10 +1210,8 @@
<skip />
<!-- no translation found for sim_restart_button (4722407842815232347) -->
<skip />
- <!-- no translation found for time_picker_dialog_title (8349362623068819295) -->
- <skip />
- <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
- <skip />
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Hlela isikhathi"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
<!-- no translation found for date_time_set (5777075614321087758) -->
<skip />
<!-- no translation found for default_permission_group (2690160991405646128) -->
@@ -1243,13 +1223,11 @@
<string name="usb_storage_activity_title" msgid="2399289999608900443">"Ukugcina Okukhulu nge-USB"</string>
<!-- no translation found for usb_storage_title (5901459041398751495) -->
<skip />
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Uxhume ifoni yakho ekhompyutheni yakho nge-USB. Khetha inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nekhadi lakho le-Andrdoid SD."</string>
- <!-- outdated translation 4796759646167247178 --> <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Uxhume ifoni yakho ekhompyutheni yakho nge-USB. Khetha inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nekhadi lakho le-Andrdoid SD."</string>
+ <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Uxhumeke kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nokugcina nge-Android USB yakho."</string>
+ <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Uxhume kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nekhadi lakho le-SD."</string>
<string name="usb_storage_button_mount" msgid="1052259930369508235">"Vula ukuginca nge-USB"</string>
- <!-- no translation found for usb_storage_error_message (3276413764430468454) -->
- <skip />
- <!-- no translation found for usb_storage_error_message (120810397713773275) -->
- <skip />
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kunenkinga yokusebenzisa ikhadi lakho le-SD lokugcina nge-USB."</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kunenkinga yokusebenzisa ikhadi lakho le-SD lokugcina nge-USB."</string>
<!-- no translation found for usb_storage_notification_title (8175892554757216525) -->
<skip />
<!-- no translation found for usb_storage_notification_message (7380082404288219341) -->
@@ -1257,7 +1235,7 @@
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vala ukugcina nge-USB"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Khetha ukuvala ukugcina nge-USB."</string>
<string name="usb_storage_stop_title" msgid="660129851708775853">"Ukugcina nge-USB kuyasebenza"</string>
- <!-- outdated translation 3613713396426604104 --> <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Ngaphambi kokuvala ukugcina nge-USB, qiniseka ukuthi wehlise (\"ukhiphe\" ikhadi lakho le-Android SD kwikhompyutha yakho."</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Ngaphambi kokuvala ukugcina nge-USB, qiniseka ukuthi wehlise (\"ukhiphe\") ukugcina nge-USB ye-Android yakho kwikhompyutha yakho."</string>
<string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Ngaphambi kokuvala ukugcina nge-USB, qiniseka ukuthi wehlise (\"ukhiphe\" ikhadi lakho le-Android SD kwikhompyutha yakho."</string>
<string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vala ukugcina nge-USB"</string>
<string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kube nenkinga yokuvala ukugcina nge-USB. Hlola ukuqiniseka ukuthi wehlise isikhungo se-USB, bese uzama futhi."</string>
@@ -1265,9 +1243,13 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Uma uvula ukugcina nge-USB, ezinye izinhlelo zokusebenza ozisebenzisayo zizoma futhi zingase zingatholakali kuze kube yilapho uvala ukugcina nge-USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Umsebenzi we-USB wehlulekile"</string>
<string name="dlg_ok" msgid="7376953167039865701">"KULUNGILE"</string>
- <!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fometha ikhadi le=SD"</string>
+ <!-- no translation found for usb_preferences_notification_title (2540843093508208861) -->
+ <skip />
+ <!-- no translation found for usb_preferece_notification_message (4715212563869699564) -->
+ <skip />
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fometha ukugcina nge-USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fometha ikhadi le=SD"</string>
- <!-- outdated translation 3621369962433523619 --> <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Uqinisekile ukuthi ufuna ukufometha ikhadi le-SD? Yonke idatha esekhadini lakho izolahleka."</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Fometha ukugcina nge-USB, usule wonke amafayela agcinwe lapho? Isinyathelo asikwazi ukuguqulwa?"</string>
<string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Uqinisekile ukuthi ufuna ukufometha ikhadi le-SD? Yonke idatha esekhadini lakho izolahleka."</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"Ifomethi"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"Ukulungisa iphutha le-USB kuxhunyiwe"</string>
@@ -1278,28 +1260,28 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string>
- <!-- outdated translation 5457603418970994050 --> <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungisa ikhadi le-SD"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungiselela ukugcina nge-USB"</string>
<string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Ilungisa ikhadi le-SD"</string>
<string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Ihlola amaphutha"</string>
- <!-- outdated translation 780477838241212997 --> <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Ikhadi le-SD elingenalutho"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Ukugcina nge-USB okungenalutho"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Ikhadi le-SD elingenalutho"</string>
- <!-- outdated translation 3817704088027829380 --> <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Ikhadi le-SD alinalutho noma lunohlelo lwesistimu olungasekelwa."</string>
+ <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Ukugcina nge-USB akunalutho noma kunohlelo lwefayela olungasekelwa."</string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Ikhadi le-SD alinalutho noma lunohlelo lwesistimu olungasekelwa."</string>
- <!-- outdated translation 6410723906019100189 --> <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Ikhadi le-SD elonakele"</string>
+ <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Ukugcina nge-USB okonakele"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Ikhadi le-SD elonakele"</string>
- <!-- outdated translation 6902531775948238989 --> <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Ikhadi le-SD lonakele. Kungase kudingeke ukuba uyifomethe futhi."</string>
+ <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Ukugcina nge-USB konakele. Kungase kudingeke ukufa ulifomethe futhi."</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Ikhadi le-SD lonakele. Kungase kudingeke ukuba uyifomethe futhi."</string>
- <!-- outdated translation 6872152882604407837 --> <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Ikhadi le-SD likhishwe ngokungalindelekile"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Ukugcina nge-USB kukhishwe ngokungalindelekile"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Ikhadi le-SD likhishwe ngokungalindelekile"</string>
- <!-- outdated translation 7260183293747448241 --> <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha ukugwema ukulahleka kwedatha."</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha ukugwema ukulahleka kwedatha."</string>
<string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha ukugwema ukulahleka kwedatha."</string>
- <!-- outdated translation 6729801130790616200 --> <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kuphephile ukukhipha ikhadi le-SD"</string>
+ <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kuvikelekile ukukhipha ukugcina nge-USB"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kuphephile ukukhipha ikhadi le-SD"</string>
- <!-- outdated translation 568841278138377604 --> <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ungakhipha ngokuphephile ikhadi le-SD."</string>
+ <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ungakhipha ngokuvikelekile ukugcina nge-USB."</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Ungakhipha ngokuphephile ikhadi le-SD."</string>
- <!-- outdated translation 8902518030404381318 --> <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ikhadi le-SD elikhishiwe"</string>
+ <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ukugcina nge-USB kukhishiwe"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Ikhadi le-SD elikhishiwe"</string>
- <!-- outdated translation 3870120652983659641 --> <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Ikhadi le-SD likhishiwe. Faka elisha."</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Ukugcina nge-USB kukhishiwe. Faka imidiya entsha."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Ikhadi le-SD likhishiwe. Faka elisha."</string>
<string name="activity_list_empty" msgid="4168820609403385789">"Ayikho imisebenzi efanayo etholakele"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"buyekeza izibalo zokusebenzisa ingxenye"</string>
@@ -1313,8 +1295,7 @@
<string name="ime_action_send" msgid="2316166556349314424">"Thumela"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Okulandelayo"</string>
<string name="ime_action_done" msgid="8971516117910934605">"Kwenziwe"</string>
- <!-- no translation found for ime_action_previous (1443550039250105948) -->
- <skip />
+ <string name="ime_action_previous" msgid="1443550039250105948">"Okwangaphambilini"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Ukwenza"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Dayela inombolo"\n"usebenzisa <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="4947405226788104538">"Yenza othintana naye"\n" usebenzisa <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1334,6 +1315,14 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"Ingqimbi 2 Yomthetho Olandelwayo Wokwenza Umbhoshongo"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Ukwabelana kwangaphambili kokhiye osekelwe ku-L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Isitifiketi sisekelwe L2TP/IPSec VPN"</string>
+ <!-- no translation found for vpn_ticker (285642105845608311) -->
+ <skip />
+ <!-- no translation found for vpn_title (5434034606697234123) -->
+ <skip />
+ <!-- no translation found for vpn_text (1610714069627824309) -->
+ <skip />
+ <!-- no translation found for vpn_text_long (4907843483284977618) -->
+ <skip />
<string name="upload_file" msgid="2897957172366730416">"Khetha ifayela"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string>
<string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
@@ -1355,60 +1344,33 @@
<item quantity="one" msgid="8167147081136579439">"okufanayo okungu-1"</item>
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ku-<xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
- <!-- no translation found for action_mode_done (7217581640461922289) -->
- <skip />
- <!-- no translation found for progress_unmounting (535863554318797377) -->
- <skip />
- <!-- no translation found for progress_unmounting (5556813978958789471) -->
- <skip />
- <!-- no translation found for progress_erasing (4183664626203056915) -->
- <skip />
- <!-- no translation found for progress_erasing (2115214724367534095) -->
- <skip />
- <!-- no translation found for format_error (4320339096529911637) -->
- <skip />
- <!-- no translation found for format_error (1343380371925238343) -->
- <skip />
- <!-- no translation found for media_bad_removal (7960864061016603281) -->
- <skip />
- <!-- no translation found for media_checking (418188720009569693) -->
- <skip />
- <!-- no translation found for media_checking (7334762503904827481) -->
- <skip />
- <!-- no translation found for media_removed (7001526905057952097) -->
- <skip />
- <!-- no translation found for media_shared (5830814349250834225) -->
- <skip />
- <!-- no translation found for media_shared (5706130568133540435) -->
- <skip />
- <!-- no translation found for media_unknown_state (729192782197290385) -->
- <skip />
- <!-- no translation found for share (1778686618230011964) -->
- <skip />
- <!-- no translation found for find (4808270900322985960) -->
- <skip />
- <!-- no translation found for websearch (4337157977400211589) -->
- <skip />
- <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
- <skip />
- <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
- <skip />
- <!-- no translation found for gpsNotifMessage (1374718023224000702) -->
- <skip />
- <!-- no translation found for gpsVerifYes (2346566072867213563) -->
- <skip />
- <!-- no translation found for gpsVerifNo (1146564937346454865) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
- <skip />
- <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
- <skip />
- <!-- no translation found for sync_really_delete (8933566316059338692) -->
- <skip />
- <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
- <skip />
- <!-- no translation found for sync_do_nothing (8717589462945226869) -->
- <skip />
+ <string name="action_mode_done" msgid="7217581640461922289">"Kwenziwe"</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Yehlisa ukugcina nge-USB..."</string>
+ <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Yehlisa ikhadi le-SD..."</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Isula ukugcina nge-USB."</string>
+ <string name="progress_erasing" product="default" msgid="2115214724367534095">"Isula ikhadi le-SD..."</string>
+ <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Yehlulekile ukusula ukugcina nge-USB"</string>
+ <string name="format_error" product="default" msgid="1343380371925238343">"Yehlulekile ukususa ikhadi le-SD."</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"Ikhadi le-SD likhishwe ngaphambi kokuba lehliswe."</string>
+ <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Ukugcina nge-USB okwamanje kusahlolwa."</string>
+ <string name="media_checking" product="default" msgid="7334762503904827481">"Ikhadi le-SD okwamanje liyahlolwa."</string>
+ <string name="media_removed" msgid="7001526905057952097">"Ikhadi le-SD likhishiwe."</string>
+ <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Ukugcina nge-USB okwamanje kusetshenziswa ikhompyutha."</string>
+ <string name="media_shared" product="default" msgid="5706130568133540435">"Ikhadi le-SD okwamanje lisetshenziswa ikhompyutha."</string>
+ <string name="media_unknown_state" msgid="729192782197290385">"Imidiya yangaphakathi kwisimo esingaziwa."</string>
+ <string name="share" msgid="1778686618230011964">"Yabelana"</string>
+ <string name="find" msgid="4808270900322985960">"Thola"</string>
+ <string name="websearch" msgid="4337157977400211589">"USesho lweWebhu"</string>
+ <string name="gpsNotifTicker" msgid="5622683912616496172">"Isicelo sendawo esiphuma ku-<xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="5446858717157416839">"Isicelo sendawo"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"Icelwe ngu-:<xliff:g id="NAME">%1$s</xliff:g><xliff:g id="SERVICE">%2$s</xliff:g>"</string>
+ <string name="gpsVerifYes" msgid="2346566072867213563">"Yebo"</string>
+ <string name="gpsVerifNo" msgid="1146564937346454865">"Cha"</string>
+ <string name="sync_too_many_deletes" msgid="5296321850662746890">"Umkhawulo wokususa ufinyelelwe"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7030265992955132593">"Kunezintwana <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> ezisusiwe ze-<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> akhawunti <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. Yini ongathanda ukuyenza?"</string>
+ <string name="sync_really_delete" msgid="8933566316059338692">"Susa izintwana."</string>
+ <string name="sync_undo_deletes" msgid="8610996708225006328">"Guqula okususiwe."</string>
+ <string name="sync_do_nothing" msgid="8717589462945226869">"Ungenzi lutho okwamanje."</string>
<!-- no translation found for vpn_notification_title_connected (3197819122581348515) -->
<skip />
<!-- no translation found for vpn_notification_title_disconnected (4614192702448522822) -->
@@ -1435,4 +1397,16 @@
<skip />
<!-- no translation found for extract_edit_menu_button (302060189057163906) -->
<skip />
+ <!-- no translation found for data_usage_warning_title (1955638862122232342) -->
+ <skip />
+ <!-- no translation found for data_usage_warning_body (3354394590936526648) -->
+ <skip />
+ <!-- no translation found for data_usage_3g_limit_title (7093334419518706686) -->
+ <skip />
+ <!-- no translation found for data_usage_4g_limit_title (7636489436819470761) -->
+ <skip />
+ <!-- no translation found for data_usage_mobile_limit_title (7869402519391631884) -->
+ <skip />
+ <!-- no translation found for data_usage_limit_body (2182247539226163759) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9c25ace..db33d1c 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -202,9 +202,14 @@
<!-- The preferred list item height. -->
<attr name="listPreferredItemHeight" format="dimension" />
- <!-- The drawable for the list divider. -->
+ <!-- A smaller, sleeker list item height. -->
+ <attr name="listPreferredItemHeightSmall" format="dimension" />
+ <!-- A larger, more robust list item height. -->
+ <attr name="listPreferredItemHeightLarge" format="dimension" />
<!-- The list item height for search results. @hide -->
<attr name="searchResultListItemHeight" format="dimension" />
+
+ <!-- The drawable for the list divider. -->
<attr name="listDivider" format="reference" />
<!-- The list divider used in alert dialogs. -->
<attr name="listDividerAlertDialog" format="reference" />
@@ -591,6 +596,11 @@
<attr name="actionOverflowButtonStyle" format="reference" />
<!-- Reference to a style for the Action Bar -->
<attr name="actionBarStyle" format="reference" />
+ <!-- Reference to a style for the split Action Bar. This style
+ controls the split component that holds the menu/action
+ buttons. actionBarStyle is still used for the primary
+ bar. -->
+ <attr name="actionBarSplitStyle" format="reference" />
<!-- Size of the Action Bar, including the contextual
bar used to present Action Modes. -->
<attr name="actionBarSize" format="dimension" >
@@ -1206,6 +1216,16 @@
<enum name="vertical" value="1" />
</attr>
+ <!-- Alignment constants. -->
+ <attr name="alignmentMode">
+ <!-- Align the bounds of the children.
+ See {@link android.widget.GridLayout#ALIGN_BOUNDS}. -->
+ <enum name="alignBounds" value="0" />
+ <!-- Align the margins of the children.
+ See {@link android.widget.GridLayout#ALIGN_MARGINS}. -->
+ <enum name="alignMargins" value="1" />
+ </attr>
+
<!-- ========================== -->
<!-- Key Codes -->
<!-- ========================== -->
@@ -1646,6 +1666,10 @@
<attr name="paddingRight" format="dimension" />
<!-- Sets the padding, in pixels, of the bottom edge; see {@link android.R.attr#padding}. -->
<attr name="paddingBottom" format="dimension" />
+ <!-- Sets the padding, in pixels, of the start edge; see {@link android.R.attr#padding}. -->
+ <attr name="paddingStart" format="dimension" />
+ <!-- Sets the padding, in pixels, of the end edge; see {@link android.R.attr#padding}. -->
+ <attr name="paddingEnd" format="dimension" />
<!-- Boolean that controls whether a view can take focus. By default the user can not
move focus to a view; by setting this attribute to true the view is
@@ -1948,6 +1972,24 @@
<!-- Locale -->
<enum name="locale" value="3" />
</attr>
+ <!-- Direction of the text. A heuristic is used to determine the resolved text direction
+ of paragraphs. -->
+ <attr name="textDirection" format="integer">
+ <!-- Default -->
+ <enum name="inherit" value="0" />
+ <!-- Default for the root view. The first strong directional character determines the
+ paragraph direction. If there is o strong directional character, the paragraph
+ direction is the view’s resolved layout direction. -->
+ <enum name="firstStrong" value="1" />
+ <!-- The paragraph direction is RTL if it contains any strong RTL character, otherwise
+ it is LTR if it contains any strong LTR characters. If there are neither, the
+ paragraph direction is the view’s resolved layout direction. -->
+ <enum name="anyRtl" value="2" />
+ <!-- The text direction is left to right. -->
+ <enum name="ltr" value="3" />
+ <!-- The text direction is right to left. -->
+ <enum name="rtl" value="4" />
+ </attr>
</declare-styleable>
<!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2106,6 +2148,12 @@
<!-- Specifies extra space on the bottom side of this view.
This space is outside this view's bounds. -->
<attr name="layout_marginBottom" format="dimension" />
+ <!-- Specifies extra space on the start side of this view.
+ This space is outside this view's bounds. -->
+ <attr name="layout_marginStart" format="dimension" />
+ <!-- Specifies extra space on the end side of this view.
+ This space is outside this view's bounds. -->
+ <attr name="layout_marginEnd" format="dimension" />
</declare-styleable>
<!-- Use <code>input-method</code> as the root tag of the XML resource that
@@ -2160,7 +2208,8 @@
<!-- The event types this serivce would like to receive as specified in
{@link android.view.accessibility.AccessibilityEvent}. This setting
can be changed at runtime by calling
- {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
<attr name="accessibilityEventTypes">
<!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.-->
<flag name="typeViewClicked" value="0x00000001" />
@@ -2184,17 +2233,24 @@
<flag name="typeTouchExplorationGestureStart" value="0x00000200" />
<!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. -->
<flag name="typeTouchExplorationGestureEnd" value="0x00000400" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events. -->
+ <flag name="typeWindowContentChanged" value="0x00000800" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED} events. -->
+ <flag name="typeViewScrolled" value="0x000001000" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} events. -->
+ <flag name="typeViewTextSelectionChanged" value="0x000002000" />
<!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
<flag name="typeAllMask" value="0xffffffff" />
</attr>
<!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages).
- This setting can be changed at runtime by calling
- {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
<attr name="packageNames" format="string" />
<!-- The feedback types this serivce provides as specified in
{@link android.accessibilityservice.AccessibilityServiceInfo}. This setting
can be changed at runtime by calling
- {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
<attr name="accessibilityFeedbackType">
<!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_SPOKEN} feedback. -->
<flag name="feedbackSpoken" value="0x00000001" />
@@ -2207,14 +2263,16 @@
<!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
<flag name="feedbackGeneric" value="0x00000010" />
</attr>
- <!-- The minimal period in milliseconds between two accessibility events are sent
- to this serivce. This setting can be changed at runtime by calling
- {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <!-- The minimal period in milliseconds between two accessibility events of the same type
+ are sent to this serivce. This setting can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->>
<attr name="notificationTimeout" format="integer" />
<!-- Additional flags as specified in
{@link android.accessibilityservice.AccessibilityServiceInfo}.
This setting can be changed at runtime by calling
- {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+ android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
<attr name="accessibilityFlags">
<!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
<flag name="flagDefault" value="0x00000001" />
@@ -2223,7 +2281,7 @@
the settings for this service. This setting cannot be changed at runtime. -->
<attr name="settingsActivity" />
<!-- Flag whether the accessibility service wants to be able to retrieve the
- focused window content. This setting cannot be changed at runtime. -->
+ active window content. This setting cannot be changed at runtime. -->
<attr name="canRetrieveWindowContent" format="boolean" />
</declare-styleable>
@@ -2541,12 +2599,12 @@
The default value is false.
See {@link android.widget.GridLayout#setUseDefaultMargins(boolean)}.-->
<attr name="useDefaultMargins" format="boolean" />
- <!-- When set to true, causes alignment to take place between the outer
- boundary of a view, as defined by its margins. When set to false,
+ <!-- When set to alignMargins, causes alignment to take place between the outer
+ boundary of a view, as defined by its margins. When set to alignBounds,
causes alignment to take place between the edges of the view.
- The default is true.
- See {@link android.widget.GridLayout#setMarginsIncludedInAlignment(boolean)}.-->
- <attr name="marginsIncludedInAlignment" format="boolean" />
+ The default is alignMargins.
+ See {@link android.widget.GridLayout#setAlignmentMode(int)}.-->
+ <attr name="alignmentMode" />
<!-- When set to true, forces row boundaries to appear in the same order
as row indices.
The default is false.
@@ -5230,4 +5288,15 @@
<attr name="disableDependentsState" />
</declare-styleable>
+ <!-- Use <code>tts-engine</code> as the root tag of the XML resource that
+ describes a text to speech engine implemented as a subclass of
+ {@link android.speech.tts.TextToSpeechService}.
+
+ The XML resource must be referenced from its
+ {@link android.speech.tts.TextToSpeech.Engine#SERVICE_META_DATA} meta-data
+ entry. -->
+ <declare-styleable name="TextToSpeechEngine">
+ <attr name="settingsActivity" />
+ </declare-styleable>
+
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f7974e9..03b332e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -235,12 +235,13 @@
<attr name="vmSafeMode" format="boolean" />
<!-- <p>Flag indicating whether the application's rendering should be hardware
- accelerated if possible. This flag is turned off by default, both for
- applications and activities.</p>
+ accelerated if possible. This flag is turned on by default for applications
+ that are targeting {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}
+ or later.</p>
<p>This flag can be set on the application and any activity declared
in the manifest. When enabled for the application, each activity is
automatically assumed to be hardware accelerated. This flag can be
- overriden in the activity tags, either turning it off (if on for the
+ overridden in the activity tags, either turning it off (if on for the
application) or on (if off for the application.)</p>
<p>When this flag is turned on for an activity (either directly or via
the application tag), every window created from the activity, including
@@ -1020,7 +1021,7 @@
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
- this is the new way to specify the screens an application is
+ this is the new way to specify the minimum screen size an application is
compatible with. This attribute provides the required minimum
"smallest screen width" (as per the -swNNNdp resource configuration)
that the application can run on. For example, a typical phone
@@ -1031,17 +1032,15 @@
or xlargeScreens attributes will be used instead. -->
<attr name="requiresSmallestWidthDp" format="integer" />
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
- this is the new way to specify the screens an application is
+ this is the new way to specify the largest screens an application is
compatible with. This attribute provides the maximum
"smallest screen width" (as per the -swNNNdp resource configuration)
that the application is designed for. If this value is smaller than
the "smallest screen width" of the device it is running on, the user
- will of offered to run it in a compatibility mode that emulates a
- smaller screen. Currently the compatibility mode only emulates
- phone screens, so it will not be used it the application provides
- a requiresSmallestWidthDp that is larger than 320. Typical values
- used with this attribute are 320 for a phone screen, 600 for a
- 7" tablet, and 720 for a 10" tablet. -->
+ is offered to run it in a compatibility mode that emulates a
+ smaller screen and zooms it to fit the screen. Currently the compatibility mode only
+ emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+ value for compatibleWidthLimitDp is larger than 320. -->
<attr name="compatibleWidthLimitDp" format="integer" />
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
this is the new way to specify the screens an application is
@@ -1050,9 +1049,9 @@
that the application can work well on. If this value is smaller than
the "smallest screen width" of the device it is running on, the
application will be forced in to screen compatibility mode with
- no way for the user to turn it off. Currently the compatibility mode
- only emulates phone screens, so even if this value is larger than 320
- the width the app runs in will be a 320 phone dimension. -->
+ no way for the user to turn it off. Currently the compatibility mode only
+ emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+ value for largestWidthLimitDp is larger than 320. -->
<attr name="largestWidthLimitDp" format="integer" />
<!-- Indicates whether the application supports smaller screen form-factors.
A small screen is defined as one with a smaller aspect ratio than
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 9d6309d..9647bb7 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -19,4 +19,5 @@
<bool name="action_bar_embed_tabs">false</bool>
<bool name="split_action_bar_is_narrow">true</bool>
<bool name="preferences_prefer_dual_pane">false</bool>
+ <bool name="show_ongoing_ime_switcher">true</bool>
</resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index e76c0e5..2a1ebfc 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,7 +18,7 @@
*/
-->
<resources>
- <drawable name="screen_background_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_light">#ffffffff</drawable>
<drawable name="screen_background_dark">#ff000000</drawable>
<drawable name="status_bar_closed_default_background">#ff000000</drawable>
<drawable name="status_bar_opened_default_background">#ff000000</drawable>
@@ -37,7 +37,7 @@
<color name="black">#ff000000</color>
<color name="transparent">#00000000</color>
<color name="background_dark">#ff000000</color>
- <color name="background_light">#fff3f3f3</color>
+ <color name="background_light">#ffffffff</color>
<color name="bright_foreground_dark">@android:color/background_light</color>
<color name="bright_foreground_light">@android:color/background_dark</color>
<color name="bright_foreground_dark_disabled">#80ffffff</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 74d942f..2c10b3d 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3,16 +3,16 @@
/*
** Copyright 2009, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this 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.
*/
-->
@@ -54,25 +54,25 @@
connected. If you use the ims apn DCT will block
any other apn from connecting until ims apn is connected-->
<bool name="ImsConnectedDefaultValue">false</bool>
-
+
<!-- Flag indicating whether the surface flinger is inefficient
at performing a blur. Used by parts of the UI to turn off
the blur effect where it isn't worth the performance hit. -->
<bool name="config_sf_slowBlur">false</bool>
-
+
<!-- The duration (in milliseconds) of a short animation. -->
<integer name="config_shortAnimTime">200</integer>
-
+
<!-- The duration (in milliseconds) of a medium-length animation. -->
<integer name="config_mediumAnimTime">400</integer>
-
+
<!-- The duration (in milliseconds) of a long animation. -->
<integer name="config_longAnimTime">500</integer>
<!-- The duration (in milliseconds) of the activity open/close and fragment open/close animations. -->
<integer name="config_activityShortDur">150</integer>
<integer name="config_activityDefaultDur">220</integer>
-
+
<!-- Duration for the dim animation behind a dialog. This may be either
a percentage, which is relative to the duration of the enter/open
animation of the window being shown that is dimming behind, or it may
@@ -83,11 +83,11 @@
maximum (let them grow as large as the screen). Actual values are
specified for -large and -xlarge configurations. -->
<dimen name="config_prefDialogWidth">320dp</dimen>
-
+
<!-- Whether dialogs should close automatically when the user touches outside
of them. This should not normally be modified. -->
<bool name="config_closeDialogWhenTouchOutside">false</bool>
-
+
<!-- The duration (in milliseconds) that the radio will scan for a signal
when there's no network connection. If the scan doesn't timeout, use zero -->
<integer name="config_radioScanningTimeout">0</integer>
@@ -98,7 +98,7 @@
<!-- This string array should be overridden by the device to present a list of network
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
- <!-- An Array of "[Connection name],[ConnectivityManager connection type],
+ <!-- An Array of "[Connection name],[ConnectivityManager.TYPE_xxxx],
[associated radio-type],[priority],[restoral-timer(ms)],[dependencyMet] -->
<!-- the 5th element "resore-time" indicates the number of milliseconds to delay
before automatically restore the default connection. Set -1 if the connection
@@ -115,6 +115,14 @@
<item>"mobile_cbs,12,0,2,60000,true"</item>
</string-array>
+ <!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
+ be controlled by systemOrSignature apps. -->
+ <integer-array translatable="false" name="config_protectedNetworks">
+ <item>10</item>
+ <item>11</item>
+ <item>12</item>
+ </integer-array>
+
<!-- This string array should be overridden by the device to present a list of radio
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
@@ -154,20 +162,16 @@
<string-array translatable="false" name="config_tether_dhcp_range">
</string-array>
- <!-- Regex array of allowable upstream ifaces for tethering - for example if you want
- tethering on a new interface called "foo2" add <item>"foo\\d"</item> to the array -->
- <!-- Interfaces will be prioritized according to the order listed -->
- <string-array translatable="false" name="config_tether_upstream_regexs">
- </string-array>
-
<!-- Regex of wired ethernet ifaces -->
<string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
- <!-- Boolean indicating if we require the use of DUN on mobile for tethering.
- Note that this defaults to false so that if you move to a carrier that
- hasn't configured anything tethering will still work. If you'd rather
- make the device untetherable on unconfigured devices, set to true -->
- <bool translatable="false" name="config_tether_dun_required">false</bool>
+ <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
+ <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
+ <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
+ <integer-array translatable="false" name="config_tether_upstream_types">
+ <item>1</item>
+ <item>4</item>
+ </integer-array>
<!-- String containing the apn value for tethering. May be overriden by secure settings
TETHER_DUN_APN. Value is a comma separated series of strings:
@@ -198,7 +202,7 @@
the slider is open. This can be set or unset depending how easily
the slider can be opened (for example, in a pocket or purse). -->
<bool name="config_bypass_keyguard_if_slider_open">true</bool>
-
+
<!-- Flag indicating whether the we should enable the automatic brightness in Settings.
Software implementation will be used if config_hardware_auto_brightness_available is not set -->
<bool name="config_automatic_brightness_available">false</bool>
@@ -208,10 +212,10 @@
<!-- If this is true, the screen will come on when you unplug usb/power/whatever. -->
<bool name="config_unplugTurnsOnScreen">false</bool>
-
+
<!-- If this is true, the screen will fade off. -->
<bool name="config_animateScreenLights">true</bool>
-
+
<!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
<!-- If true, the screen can be rotated via the accelerometer in all 4
@@ -296,7 +300,7 @@
<item>20</item>
<item>21</item>
</integer-array>
-
+
<!-- Vibrator pattern for feedback about touching a virtual key -->
<integer-array name="config_virtualKeyVibePattern">
<item>0</item>
@@ -376,8 +380,8 @@
<!-- Allow the menu hard key to be disabled in LockScreen on some devices -->
<bool name="config_disableMenuKeyInLockScreen">false</bool>
- <!-- Show sliding tab before lockscreen -->
- <bool name="config_enableSlidingTabFirst">true</bool>
+ <!-- Don't show lock screen before unlock screen (PIN/pattern/password) -->
+ <bool name="config_enableLockBeforeUnlockScreen">false</bool>
<!-- Diable lockscreen rotation by default -->
<bool name="config_enableLockScreenRotation">false</bool>
@@ -456,7 +460,7 @@
This feature should be disabled for most devices. -->
<integer name="config_virtualKeyQuietTimeMillis">0</integer>
- <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
+ <!-- Component name of the default wallpaper. This will be ImageWallpaper if not
specified -->
<string name="default_wallpaper_component">@null</string>
@@ -636,10 +640,26 @@
<!-- Set to true if the RSSI should always display CDMA signal strength even on EVDO -->
<bool name="config_alwaysUseCdmaRssi">false</bool>
+
<!-- If this value is true, duplicate Source/Destination port fields
in WDP header of some carriers OMADM wap push are supported.
ex: MSGTYPE-TotalSegments-CurrentSegment
-SourcePortDestPort-SourcePortDestPort-OMADM PDU
If false, not supported. -->
<bool name="config_duplicate_port_omadm_wappush">false</bool>
+
+ <!-- Maximum numerical value that will be shown in a status bar
+ notification icon or in the notification itself. Will be replaced
+ with @string/status_bar_notification_info_overflow when shown in the
+ UI. -->
+ <integer name="status_bar_notification_info_maxnum">999</integer>
+
+ <!-- Path to an ISO image to be shared with via USB mass storage.
+ This is intended to allow packaging drivers or tools for installation on a PC. -->
+ <string translatable="false" name="config_isoImagePath"></string>
+
+ <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
+ autodetected from the Configuration. -->
+ <bool name="config_showNavigationBar">false</bool>
+
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 0725c2f..a5e5f70 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -118,5 +118,19 @@
<!-- Default height of an action bar. -->
<dimen name="action_bar_default_height">48dip</dimen>
<!-- Vertical padding around action bar icons. -->
- <dimen name="action_bar_icon_vertical_padding">4dip</dimen>
+ <dimen name="action_bar_icon_vertical_padding">8dip</dimen>
+ <!-- Text size for action bar titles -->
+ <dimen name="action_bar_title_text_size">18dp</dimen>
+ <!-- Text size for action bar subtitles -->
+ <dimen name="action_bar_subtitle_text_size">14dp</dimen>
+
+ <!-- Size of clock font in LockScreen on Unsecure unlock screen. -->
+ <dimen name="keyguard_lockscreen_clock_font_size">80sp</dimen>
+
+ <!-- Size of status line font on Unsecure unlock LockScreen. -->
+ <dimen name="keyguard_lockscreen_status_line_font_size">14sp</dimen>
+
+ <!-- Size of right margin on Unsecure unlock LockScreen -->
+ <dimen name="keyguard_lockscreen_status_line_font_right_margin">45dip</dimen>
+
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index be2997e..db6f98f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1733,7 +1733,7 @@
<public type="attr" name="columnCount" />
<public type="attr" name="columnOrderPreserved" />
<public type="attr" name="useDefaultMargins" />
- <public type="attr" name="marginsIncludedInAlignment" />
+ <public type="attr" name="alignmentMode" />
<public type="attr" name="layout_row" />
<public type="attr" name="layout_rowSpan" />
@@ -1766,8 +1766,21 @@
<public type="attr" name="feedbackCount" />
<public type="attr" name="verticalOffset" />
<public type="attr" name="horizontalOffset" />
+ <public type="attr" name="listPreferredItemHeightLarge" />
+ <public type="attr" name="listPreferredItemHeightSmall" />
+
+ <public type="attr" name="paddingStart"/>
+ <public type="attr" name="paddingEnd"/>
+ <public type="attr" name="layout_marginStart"/>
+ <public type="attr" name="layout_marginEnd"/>
+
+ <public type="attr" name="actionBarSplitStyle" />
<public type="style" name="Widget.Holo.Button.Borderless.Small" />
<public type="style" name="Widget.Holo.Light.Button.Borderless.Small" />
+ <public type="integer" name="status_bar_notification_info_maxnum" />
+ <public type="string" name="status_bar_notification_info_overflow" />
+
+ <public type="attr" name="textDirection"/>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d7b7dd0..88ed9c6b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -339,10 +339,12 @@
<!-- status message in phone options dialog for when airplane mode is off -->
<string name="global_actions_airplane_mode_off_status">Airplane mode is OFF</string>
- <!-- Text to use when the number in a notification info is too large (> 100). Most likely does not need
- to be translated. We do this so, for example, if the user has tens of thousands of unread
- emails, the whole notification isn't taken over by the number. [CHAR LIMIT=5] -->
- <string name="status_bar_notification_info_overflow">100+</string>
+ <!-- Text to use when the number in a notification info is too large
+ (greater than status_bar_notification_info_maxnum, defined in
+ values/config.xml) and must be truncated. May need to be localized
+ for most appropriate textual indicator of "more than X".
+ [CHAR LIMIT=4] -->
+ <string name="status_bar_notification_info_overflow">999+</string>
<!-- Displayed to the user to tell them that they have started up the phone in "safe mode" -->
<string name="safeMode">Safe mode</string>
@@ -1441,6 +1443,11 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_manageNetworkPolicy">Allows an application to manage network policies and define application-specific rules.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_modifyNetworkAccounting">modify network usage accounting</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_modifyNetworkAccounting">Allows modification of how network usage is accounted against applications. Not for use by normal applications.</string>
+
<!-- Policy administration -->
<!-- Title of policy access to limiting the user's password choices -->
@@ -2606,6 +2613,11 @@
<!-- USB_STORAGE_ERROR dialog ok button-->
<string name="dlg_ok">OK</string>
+ <!-- USB_PREFERENCES: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across. This is the title -->
+ <string name="usb_preferences_notification_title">USB connected</string>
+ <!-- See USB_PREFERENCES. This is the message. -->
+ <string name="usb_preferece_notification_message">Select to configure USB file transfer.</string>
+
<!-- External media format dialog strings -->
<!-- This is the label for the activity, and should never be visible to the user. -->
<!-- See EXTMEDIA_FORMAT. EXTMEDIA_FORMAT_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to format the SD card. This is the title. [CHAR LIMIT=20] -->
@@ -2952,4 +2964,26 @@
<!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_limit_body">tap to enable</string>
+ <!-- SSL Certificate dialogs -->
+ <!-- Title for an SSL Certificate dialog -->
+ <string name="ssl_certificate">Security certificate</string>
+ <!-- Message on an SSL Certificate dialog -->
+ <string name="ssl_certificate_is_valid">This certificate is valid.</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="issued_to">Issued to:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="common_name">Common name:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="org_name">Organization:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="org_unit">Organizational unit:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="issued_by">Issued by:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="validity_period">Validity:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="issued_on">Issued on:</string>
+ <!-- Label for an information field on an SSL Certificate Dialog -->
+ <string name="expires_on">Expires on:</string>
+
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6e80326..5244b74 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -227,15 +227,15 @@
<style name="TextAppearance.StatusBar.Icon">
</style>
<style name="TextAppearance.StatusBar.EventContent">
- <item name="android:textColor">#ff999999</item>
- <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textSize">13sp</item>
</style>
<style name="TextAppearance.StatusBar.EventContent.Title">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:textStyle">bold</item>
</style>
<style name="TextAppearance.StatusBar.EventContent.Info">
- <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
- <item name="android:textColor">#ff272727</item>
+ <item name="android:textSize">13sp</item>
</style>
<style name="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1118,9 +1118,9 @@
<style name="Widget.ActionButton">
<item name="android:background">?android:attr/selectableItemBackground</item>
- <item name="android:paddingLeft">16dip</item>
- <item name="android:paddingRight">16dip</item>
- <item name="android:minWidth">64dip</item>
+ <item name="android:paddingLeft">12dip</item>
+ <item name="android:paddingRight">12dip</item>
+ <item name="android:minWidth">56dip</item>
<item name="android:minHeight">?android:attr/actionBarSize</item>
</style>
@@ -1296,10 +1296,12 @@
<style name="TextAppearance.Holo.Widget.ActionBar.Title"
parent="TextAppearance.Holo.Medium">
+ <item name="android:textSize">@android:dimen/action_bar_title_text_size</item>
</style>
<style name="TextAppearance.Holo.Widget.ActionBar.Subtitle"
parent="TextAppearance.Holo.Small">
+ <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item>
</style>
<style name="TextAppearance.Holo.Widget.ActionMode">
@@ -1496,6 +1498,7 @@
<style name="Holo.ButtonBar.AlertDialog">
<item name="android:background">@null</item>
+ <item name="android:dividerPadding">0dp</item>
</style>
<style name="Widget.Holo.TextView" parent="Widget.TextView">
@@ -1787,18 +1790,16 @@
</style>
<style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
- <item name="android:minWidth">64dip</item>
+ <item name="android:minWidth">56dip</item>
<item name="android:gravity">center</item>
- <item name="android:paddingLeft">16dip</item>
- <item name="android:paddingRight">16dip</item>
+ <item name="android:paddingLeft">12dip</item>
+ <item name="android:paddingRight">12dip</item>
<item name="android:scaleType">center</item>
</style>
<style name="Widget.Holo.ActionButton.Overflow">
<item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_dark</item>
<item name="android:background">?android:attr/selectableItemBackground</item>
- <item name="android:paddingLeft">16dip</item>
- <item name="android:paddingRight">16dip</item>
<item name="android:contentDescription">@string/action_menu_overflow_description</item>
</style>
@@ -1905,6 +1906,7 @@
<style name="Holo.Light.ButtonBar.AlertDialog">
<item name="android:background">@null</item>
+ <item name="android:dividerPadding">0dp</item>
</style>
<style name="Holo.Light.SegmentedButton" parent="SegmentedButton">
@@ -2140,8 +2142,6 @@
<style name="Widget.Holo.Light.ActionButton.Overflow">
<item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_light</item>
- <item name="android:paddingLeft">16dip</item>
- <item name="android:paddingRight">16dip</item>
<item name="android:contentDescription">@string/action_menu_overflow_description</item>
</style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 4a43e32..78e9975 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -95,7 +95,9 @@
<!-- List attributes -->
<item name="listPreferredItemHeight">64dip</item>
- <item name="dropdownListPreferredItemHeight">64dip</item>
+ <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeight</item>
+ <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeight</item>
+ <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
@@ -278,6 +280,7 @@
<item name="actionModeStyle">@style/Widget.ActionMode</item>
<item name="actionModeCloseButtonStyle">@style/Widget.ActionButton.CloseMode</item>
<item name="actionBarStyle">@android:style/Widget.ActionBar</item>
+ <item name="actionBarSplitStyle">?android:attr/actionBarStyle</item>
<item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item>
<item name="actionMenuTextAppearance">?android:attr/textAppearanceMedium</item>
@@ -691,17 +694,14 @@
<!-- Theme for the search input bar. -->
<style name="Theme.SearchBar" parent="Theme.Holo.Light.Panel">
- <item name="windowContentOverlay">@null</item>
<item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_light</item>
</style>
<style name="Theme.Holo.SearchBar" parent="Theme.Holo.Panel">
- <item name="windowContentOverlay">@null</item>
<item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_dark</item>
</style>
<style name="Theme.Holo.Light.SearchBar" parent="Theme.Holo.Light.Panel">
- <item name="windowContentOverlay">@null</item>
<item name="actionModeBackground">@android:drawable/cab_background_opaque_holo_light</item>
</style>
@@ -861,7 +861,9 @@
<!-- List attributes -->
<item name="listPreferredItemHeight">64dip</item>
- <item name="dropdownListPreferredItemHeight">48dip</item>
+ <item name="listPreferredItemHeightSmall">48dip</item>
+ <item name="listPreferredItemHeightLarge">80dip</item>
+ <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeightSmall</item>
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
@@ -1150,7 +1152,9 @@
<!-- List attributes -->
<item name="listPreferredItemHeight">64dip</item>
- <item name="dropdownListPreferredItemHeight">48dip</item>
+ <item name="listPreferredItemHeightSmall">48dip</item>
+ <item name="listPreferredItemHeightLarge">80dip</item>
+ <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeightSmall</item>
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 5250a7c..3cb64c7 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -16,6 +16,8 @@
package android.net;
+import static android.net.NetworkStats.TAG_NONE;
+
import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
@@ -29,14 +31,14 @@
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024)
- .addEntry(TEST_IFACE, 102, 1024, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
+ .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
- assertEquals(2, stats.findIndex(TEST_IFACE, 102));
- assertEquals(2, stats.findIndex(TEST_IFACE, 102));
- assertEquals(0, stats.findIndex(TEST_IFACE, 100));
- assertEquals(-1, stats.findIndex(TEST_IFACE, 6));
+ assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
+ assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE));
+ assertEquals(0, stats.findIndex(TEST_IFACE, 100, TAG_NONE));
+ assertEquals(-1, stats.findIndex(TEST_IFACE, 6, TAG_NONE));
}
public void testAddEntryGrow() throws Exception {
@@ -45,15 +47,15 @@
assertEquals(0, stats.size);
assertEquals(2, stats.iface.length);
- stats.addEntry(TEST_IFACE, TEST_UID, 1L, 2L);
- stats.addEntry(TEST_IFACE, TEST_UID, 2L, 2L);
+ stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 2L);
+ stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L);
assertEquals(2, stats.size);
assertEquals(2, stats.iface.length);
- stats.addEntry(TEST_IFACE, TEST_UID, 3L, 4L);
- stats.addEntry(TEST_IFACE, TEST_UID, 4L, 4L);
- stats.addEntry(TEST_IFACE, TEST_UID, 5L, 5L);
+ stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 4L);
+ stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 4L);
+ stats.addEntry(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 5L);
assertEquals(5, stats.size);
assertTrue(stats.iface.length >= 5);
@@ -65,14 +67,31 @@
assertEquals(5L, stats.rx[4]);
}
+ public void testCombineExisting() throws Exception {
+ final NetworkStats stats = new NetworkStats(TEST_START, 10);
+
+ stats.addEntry(TEST_IFACE, 1001, TAG_NONE, 512L, 256L);
+ stats.addEntry(TEST_IFACE, 1001, 0xff, 128L, 128L);
+ stats.combineEntry(TEST_IFACE, 1001, TAG_NONE, -128L, -128L);
+
+ assertStatsEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 128L);
+ assertStatsEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 128L);
+
+ // now try combining that should create row
+ stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
+ assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
+ stats.combineEntry(TEST_IFACE, 5005, TAG_NONE, 128L, 128L);
+ assertStatsEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 256L);
+ }
+
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
final NetworkStats result = after.subtract(before);
@@ -85,12 +104,12 @@
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, 1025, 2)
- .addEntry(TEST_IFACE, 101, 3, 1028);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1025L, 2L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 3L, 1028L);
final NetworkStats result = after.subtract(before);
@@ -103,13 +122,13 @@
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L);
final NetworkStats after = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, 1024, 0)
- .addEntry(TEST_IFACE, 101, 0, 1024)
- .addEntry(TEST_IFACE, 102, 1024, 1024);
+ .addEntry(TEST_IFACE, 100, TAG_NONE, 1024L, 0L)
+ .addEntry(TEST_IFACE, 101, TAG_NONE, 0L, 1024L)
+ .addEntry(TEST_IFACE, 102, TAG_NONE, 1024L, 1024L);
final NetworkStats result = after.subtract(before);
@@ -122,4 +141,13 @@
assertEquals(1024, result.tx[2]);
}
+ private static void assertStatsEntry(
+ NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
+ assertEquals(iface, stats.iface[i]);
+ assertEquals(uid, stats.uid[i]);
+ assertEquals(tag, stats.tag[i]);
+ assertEquals(rx, stats.rx[i]);
+ assertEquals(tx, stats.tx[i]);
+ }
+
}
diff --git a/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
index da77298..cf9e6e6 100644
--- a/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
+++ b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
@@ -28,9 +28,17 @@
import java.io.StringWriter;
import junit.framework.TestCase;
import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicHeader;
+/**
+ * Tests for various regressions and problems with DefaultHttpClient. This is
+ * not a comprehensive test!
+ */
public final class DefaultHttpClientTest extends TestCase {
private MockWebServer server = new MockWebServer();
@@ -87,4 +95,40 @@
reader.close();
return writer.toString();
}
+
+ // http://code.google.com/p/android/issues/detail?id=16051
+ public void testDigestSchemeAlgorithms() throws Exception {
+ authenticateDigestAlgorithm("MD5");
+ authenticateDigestAlgorithm("MD5-sess");
+ authenticateDigestAlgorithm("md5");
+ authenticateDigestAlgorithm("md5-sess");
+ authenticateDigestAlgorithm("md5-SESS");
+ authenticateDigestAlgorithm("MD5-SESS");
+ try {
+ authenticateDigestAlgorithm("MD5-");
+ } catch (AuthenticationException expected) {
+ }
+ try {
+ authenticateDigestAlgorithm("MD6");
+ } catch (AuthenticationException expected) {
+ }
+ try {
+ authenticateDigestAlgorithm("MD");
+ } catch (AuthenticationException expected) {
+ }
+ try {
+ authenticateDigestAlgorithm("");
+ } catch (AuthenticationException expected) {
+ }
+ }
+
+ private void authenticateDigestAlgorithm(String algorithm) throws Exception {
+ String challenge = "Digest realm=\"protected area\", "
+ + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
+ + "algorithm=" + algorithm;
+ DigestScheme digestScheme = new DigestScheme();
+ digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge));
+ HttpGet get = new HttpGet();
+ digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get);
+ }
}
diff --git a/core/tests/coretests/src/android/pim/EventRecurrenceTest.java b/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
new file mode 100644
index 0000000..05000f1
--- /dev/null
+++ b/core/tests/coretests/src/android/pim/EventRecurrenceTest.java
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.pim;
+
+import android.pim.EventRecurrence.InvalidFormatException;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Test android.pim.EventRecurrence.
+ *
+ * adb shell am instrument -w -e class android.pim.EventRecurrenceTest \
+ * com.android.frameworks.coretests/android.test.InstrumentationTestRunner
+ */
+public class EventRecurrenceTest extends TestCase {
+
+ @SmallTest
+ public void test0() throws Exception {
+ verifyRecurType("FREQ=SECONDLY",
+ /* int freq */ EventRecurrence.SECONDLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test1() throws Exception {
+ verifyRecurType("FREQ=MINUTELY",
+ /* int freq */ EventRecurrence.MINUTELY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test2() throws Exception {
+ verifyRecurType("FREQ=HOURLY",
+ /* int freq */ EventRecurrence.HOURLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test3() throws Exception {
+ verifyRecurType("FREQ=DAILY",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test4() throws Exception {
+ verifyRecurType("FREQ=WEEKLY",
+ /* int freq */ EventRecurrence.WEEKLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test5() throws Exception {
+ verifyRecurType("FREQ=MONTHLY",
+ /* int freq */ EventRecurrence.MONTHLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test6() throws Exception {
+ verifyRecurType("FREQ=YEARLY",
+ /* int freq */ EventRecurrence.YEARLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test7() throws Exception {
+ // with an until
+ verifyRecurType("FREQ=DAILY;UNTIL=112233T223344Z",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ "112233T223344Z",
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test8() throws Exception {
+ // with a count
+ verifyRecurType("FREQ=DAILY;COUNT=334",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 334,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test9() throws Exception {
+ // with a count
+ verifyRecurType("FREQ=DAILY;INTERVAL=5000",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 5000,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @SmallTest
+ public void test10() throws Exception {
+ // verifyRecurType all of the BY* ones with one element
+ verifyRecurType("FREQ=DAILY"
+ + ";BYSECOND=0"
+ + ";BYMINUTE=1"
+ + ";BYHOUR=2"
+ + ";BYMONTHDAY=30"
+ + ";BYYEARDAY=300"
+ + ";BYWEEKNO=53"
+ + ";BYMONTH=12"
+ + ";BYSETPOS=-15"
+ + ";WKST=SU",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ new int[]{0},
+ /* int[] byminute */ new int[]{1},
+ /* int[] byhour */ new int[]{2},
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ new int[]{30},
+ /* int[] byyearday */ new int[]{300},
+ /* int[] byweekno */ new int[]{53},
+ /* int[] bymonth */ new int[]{12},
+ /* int[] bysetpos */ new int[]{-15},
+ /* int wkst */ EventRecurrence.SU
+ );
+ }
+
+ @SmallTest
+ public void test11() throws Exception {
+ // verifyRecurType all of the BY* ones with one element
+ verifyRecurType("FREQ=DAILY"
+ + ";BYSECOND=0,30,59"
+ + ";BYMINUTE=0,41,59"
+ + ";BYHOUR=0,4,23"
+ + ";BYMONTHDAY=-31,-1,1,31"
+ + ";BYYEARDAY=-366,-1,1,366"
+ + ";BYWEEKNO=-53,-1,1,53"
+ + ";BYMONTH=1,12"
+ + ";BYSETPOS=1,2,3,4,500,10000"
+ + ";WKST=SU",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ new int[]{0, 30, 59},
+ /* int[] byminute */ new int[]{0, 41, 59},
+ /* int[] byhour */ new int[]{0, 4, 23},
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ new int[]{-31, -1, 1, 31},
+ /* int[] byyearday */ new int[]{-366, -1, 1, 366},
+ /* int[] byweekno */ new int[]{-53, -1, 1, 53},
+ /* int[] bymonth */ new int[]{1, 12},
+ /* int[] bysetpos */ new int[]{1, 2, 3, 4, 500, 10000},
+ /* int wkst */ EventRecurrence.SU
+ );
+ }
+
+ private static class Check {
+ Check(String k, int... v) {
+ key = k;
+ values = v;
+ }
+
+ String key;
+ int[] values;
+ }
+
+ // this is a negative verifyRecurType case to verifyRecurType the range of the numbers accepted
+ @SmallTest
+ public void test12() throws Exception {
+ Check[] checks = new Check[]{
+ new Check("BYSECOND", -100, -1, 60, 100),
+ new Check("BYMINUTE", -100, -1, 60, 100),
+ new Check("BYHOUR", -100, -1, 24, 100),
+ new Check("BYMONTHDAY", -100, -32, 0, 32, 100),
+ new Check("BYYEARDAY", -400, -367, 0, 367, 400),
+ new Check("BYWEEKNO", -100, -54, 0, 54, 100),
+ new Check("BYMONTH", -100, -5, 0, 13, 100)
+ };
+
+ for (Check ck : checks) {
+ for (int n : ck.values) {
+ String recur = "FREQ=DAILY;" + ck.key + "=" + n;
+ try {
+ EventRecurrence er = new EventRecurrence();
+ er.parse(recur);
+ fail("Negative verifyRecurType failed. "
+ + " parse failed to throw an exception for '"
+ + recur + "'");
+ } catch (EventRecurrence.InvalidFormatException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ // verifyRecurType BYDAY
+ @SmallTest
+ public void test13() throws Exception {
+ verifyRecurType("FREQ=DAILY;BYDAY=1SU,-2MO,+33TU,WE,TH,FR,SA",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.SU,
+ EventRecurrence.MO,
+ EventRecurrence.TU,
+ EventRecurrence.WE,
+ EventRecurrence.TH,
+ EventRecurrence.FR,
+ EventRecurrence.SA
+ },
+ /* int[] bydayNum */ new int[]{1, -2, 33, 0, 0, 0, 0},
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ @Suppress
+ // Repro bug #2331761 - this should fail because of the last comma into BYDAY
+ public void test14() throws Exception {
+ verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;BYDAY=MO,TU,WE,",
+ /* int freq */ EventRecurrence.WEEKLY,
+ /* String until */ "20100129T130000Z",
+ /* int count */ 0,
+ /* int interval */ 1,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.MO,
+ EventRecurrence.TU,
+ EventRecurrence.WE,
+ },
+ /* int[] bydayNum */ new int[]{0, 0, 0},
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // This test should pass
+ public void test15() throws Exception {
+ verifyRecurType("FREQ=WEEKLY;WKST=MO;UNTIL=20100129T130000Z;INTERVAL=1;"
+ + "BYDAY=MO,TU,WE,TH,FR,SA,SU",
+ /* int freq */ EventRecurrence.WEEKLY,
+ /* String until */ "20100129T130000Z",
+ /* int count */ 0,
+ /* int interval */ 1,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.MO,
+ EventRecurrence.TU,
+ EventRecurrence.WE,
+ EventRecurrence.TH,
+ EventRecurrence.FR,
+ EventRecurrence.SA,
+ EventRecurrence.SU
+ },
+ /* int[] bydayNum */ new int[]{0, 0, 0, 0, 0, 0, 0},
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // Sample coming from RFC2445
+ public void test16() throws Exception {
+ verifyRecurType("FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1",
+ /* int freq */ EventRecurrence.MONTHLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.MO,
+ EventRecurrence.TU,
+ EventRecurrence.WE,
+ EventRecurrence.TH,
+ EventRecurrence.FR
+ },
+ /* int[] bydayNum */ new int[] {0, 0, 0, 0, 0},
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ new int[] { -1 },
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // Sample coming from RFC2445
+ public void test17() throws Exception {
+ verifyRecurType("FREQ=DAILY;COUNT=10;INTERVAL=2",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 10,
+ /* int interval */ 2,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // Sample coming from RFC2445
+ public void test18() throws Exception {
+ verifyRecurType("FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10",
+ /* int freq */ EventRecurrence.YEARLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.SU
+ },
+ /* int[] bydayNum */ new int[] { -1 },
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ new int[] { 10 },
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // Sample coming from bug #1640517
+ public void test19() throws Exception {
+ verifyRecurType("FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
+ /* int freq */ EventRecurrence.YEARLY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ new int[] {
+ EventRecurrence.TH
+ },
+ /* int[] bydayNum */ new int[] { 0 },
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ new int[] { 3 },
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ // for your copying pleasure
+ public void fakeTestXX() throws Exception {
+ verifyRecurType("FREQ=DAILY;",
+ /* int freq */ EventRecurrence.DAILY,
+ /* String until */ null,
+ /* int count */ 0,
+ /* int interval */ 0,
+ /* int[] bysecond */ null,
+ /* int[] byminute */ null,
+ /* int[] byhour */ null,
+ /* int[] byday */ null,
+ /* int[] bydayNum */ null,
+ /* int[] bymonthday */ null,
+ /* int[] byyearday */ null,
+ /* int[] byweekno */ null,
+ /* int[] bymonth */ null,
+ /* int[] bysetpos */ null,
+ /* int wkst */ EventRecurrence.MO
+ );
+ }
+
+ private static void cmp(int vlen, int[] v, int[] correct, String name) {
+ if ((correct == null && v != null)
+ || (correct != null && v == null)) {
+ throw new RuntimeException("One is null, one isn't for " + name
+ + ": correct=" + Arrays.toString(correct)
+ + " actual=" + Arrays.toString(v));
+ }
+ if ((correct == null && vlen != 0)
+ || (vlen != (correct == null ? 0 : correct.length))) {
+ throw new RuntimeException("Reported length mismatch for " + name
+ + ": correct=" + ((correct == null) ? "null" : correct.length)
+ + " actual=" + vlen);
+ }
+ if (correct == null) {
+ return;
+ }
+ if (v.length < correct.length) {
+ throw new RuntimeException("Array length mismatch for " + name
+ + ": correct=" + Arrays.toString(correct)
+ + " actual=" + Arrays.toString(v));
+ }
+ for (int i = 0; i < correct.length; i++) {
+ if (v[i] != correct[i]) {
+ throw new RuntimeException("Array value mismatch for " + name
+ + ": correct=" + Arrays.toString(correct)
+ + " actual=" + Arrays.toString(v));
+ }
+ }
+ }
+
+ private static boolean eq(String a, String b) {
+ if ((a == null && b != null) || (a != null && b == null)) {
+ return false;
+ } else {
+ return a == b || a.equals(b);
+ }
+ }
+
+ private static void verifyRecurType(String recur,
+ int freq, String until, int count, int interval,
+ int[] bysecond, int[] byminute, int[] byhour,
+ int[] byday, int[] bydayNum, int[] bymonthday,
+ int[] byyearday, int[] byweekno, int[] bymonth,
+ int[] bysetpos, int wkst) {
+ EventRecurrence eventRecurrence = new EventRecurrence();
+ eventRecurrence.parse(recur);
+ if (eventRecurrence.freq != freq
+ || !eq(eventRecurrence.until, until)
+ || eventRecurrence.count != count
+ || eventRecurrence.interval != interval
+ || eventRecurrence.wkst != wkst) {
+ System.out.println("Error... got:");
+ print(eventRecurrence);
+ System.out.println("expected:");
+ System.out.println("{");
+ System.out.println(" freq=" + freq);
+ System.out.println(" until=" + until);
+ System.out.println(" count=" + count);
+ System.out.println(" interval=" + interval);
+ System.out.println(" wkst=" + wkst);
+ System.out.println(" bysecond=" + Arrays.toString(bysecond));
+ System.out.println(" byminute=" + Arrays.toString(byminute));
+ System.out.println(" byhour=" + Arrays.toString(byhour));
+ System.out.println(" byday=" + Arrays.toString(byday));
+ System.out.println(" bydayNum=" + Arrays.toString(bydayNum));
+ System.out.println(" bymonthday=" + Arrays.toString(bymonthday));
+ System.out.println(" byyearday=" + Arrays.toString(byyearday));
+ System.out.println(" byweekno=" + Arrays.toString(byweekno));
+ System.out.println(" bymonth=" + Arrays.toString(bymonth));
+ System.out.println(" bysetpos=" + Arrays.toString(bysetpos));
+ System.out.println("}");
+ throw new RuntimeException("Mismatch in fields");
+ }
+ cmp(eventRecurrence.bysecondCount, eventRecurrence.bysecond, bysecond, "bysecond");
+ cmp(eventRecurrence.byminuteCount, eventRecurrence.byminute, byminute, "byminute");
+ cmp(eventRecurrence.byhourCount, eventRecurrence.byhour, byhour, "byhour");
+ cmp(eventRecurrence.bydayCount, eventRecurrence.byday, byday, "byday");
+ cmp(eventRecurrence.bydayCount, eventRecurrence.bydayNum, bydayNum, "bydayNum");
+ cmp(eventRecurrence.bymonthdayCount, eventRecurrence.bymonthday, bymonthday, "bymonthday");
+ cmp(eventRecurrence.byyeardayCount, eventRecurrence.byyearday, byyearday, "byyearday");
+ cmp(eventRecurrence.byweeknoCount, eventRecurrence.byweekno, byweekno, "byweekno");
+ cmp(eventRecurrence.bymonthCount, eventRecurrence.bymonth, bymonth, "bymonth");
+ cmp(eventRecurrence.bysetposCount, eventRecurrence.bysetpos, bysetpos, "bysetpos");
+ }
+
+ private static void print(EventRecurrence er) {
+ System.out.println("{");
+ System.out.println(" freq=" + er.freq);
+ System.out.println(" until=" + er.until);
+ System.out.println(" count=" + er.count);
+ System.out.println(" interval=" + er.interval);
+ System.out.println(" wkst=" + er.wkst);
+ System.out.println(" bysecond=" + Arrays.toString(er.bysecond));
+ System.out.println(" bysecondCount=" + er.bysecondCount);
+ System.out.println(" byminute=" + Arrays.toString(er.byminute));
+ System.out.println(" byminuteCount=" + er.byminuteCount);
+ System.out.println(" byhour=" + Arrays.toString(er.byhour));
+ System.out.println(" byhourCount=" + er.byhourCount);
+ System.out.println(" byday=" + Arrays.toString(er.byday));
+ System.out.println(" bydayNum=" + Arrays.toString(er.bydayNum));
+ System.out.println(" bydayCount=" + er.bydayCount);
+ System.out.println(" bymonthday=" + Arrays.toString(er.bymonthday));
+ System.out.println(" bymonthdayCount=" + er.bymonthdayCount);
+ System.out.println(" byyearday=" + Arrays.toString(er.byyearday));
+ System.out.println(" byyeardayCount=" + er.byyeardayCount);
+ System.out.println(" byweekno=" + Arrays.toString(er.byweekno));
+ System.out.println(" byweeknoCount=" + er.byweeknoCount);
+ System.out.println(" bymonth=" + Arrays.toString(er.bymonth));
+ System.out.println(" bymonthCount=" + er.bymonthCount);
+ System.out.println(" bysetpos=" + Arrays.toString(er.bysetpos));
+ System.out.println(" bysetposCount=" + er.bysetposCount);
+ System.out.println("}");
+ }
+
+
+ /** A list of valid rules. The parser must accept these. */
+ private static final String[] GOOD_RRULES = {
+ /* extracted wholesale from from RFC 2445 section 4.8.5.4 */
+ "FREQ=DAILY;COUNT=10",
+ "FREQ=DAILY;UNTIL=19971224T000000Z",
+ "FREQ=DAILY;INTERVAL=2",
+ "FREQ=DAILY;INTERVAL=10;COUNT=5",
+ "FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA",
+ "FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1",
+ "FREQ=WEEKLY;COUNT=10",
+ "FREQ=WEEKLY;UNTIL=19971224T000000Z",
+ "FREQ=WEEKLY;INTERVAL=2;WKST=SU",
+ "FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH",
+ "FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH",
+ "FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR",
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH",
+ "FREQ=MONTHLY;COUNT=10;BYDAY=1FR",
+ "FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR",
+ "FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU",
+ "FREQ=MONTHLY;COUNT=6;BYDAY=-2MO",
+ "FREQ=MONTHLY;BYMONTHDAY=-3",
+ "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15",
+ "FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1",
+ "FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15",
+ "FREQ=MONTHLY;INTERVAL=2;BYDAY=TU",
+ "FREQ=YEARLY;COUNT=10;BYMONTH=6,7",
+ "FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3",
+ "FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200",
+ "FREQ=YEARLY;BYDAY=20MO",
+ "FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO",
+ "FREQ=YEARLY;BYMONTH=3;BYDAY=TH",
+ "FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8",
+ "FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13",
+ "FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13",
+ "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8",
+ "FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3",
+ "FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2",
+ "FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z",
+ "FREQ=MINUTELY;INTERVAL=15;COUNT=6",
+ "FREQ=MINUTELY;INTERVAL=90;COUNT=4",
+ "FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40",
+ "FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16",
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO",
+ "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU",
+ /* a few more */
+ "FREQ=SECONDLY;BYSECOND=0,15,59",
+ "FREQ=MINUTELY;BYMINUTE=0,15,59",
+ "FREQ=HOURLY;BYHOUR=+0,+15,+23",
+ "FREQ=DAILY;X-WHATEVER=blah", // fails on old parser
+ //"freq=daily;wkst=su", // fails on old parser
+ };
+
+ /** The parser must reject these. */
+ private static final String[] BAD_RRULES = {
+ "INTERVAL=4;FREQ=YEARLY", // FREQ must come first
+ "FREQ=MONTHLY;FREQ=MONTHLY", // can't specify twice
+ "FREQ=MONTHLY;COUNT=1;COUNT=1", // can't specify twice
+ "FREQ=SECONDLY;BYSECOND=60", // range
+ "FREQ=MINUTELY;BYMINUTE=-1", // range
+ "FREQ=HOURLY;BYHOUR=24", // range
+ "FREQ=YEARLY;BYMONTHDAY=0", // zero not valid
+ //"FREQ=YEARLY;COUNT=1;UNTIL=12345", // can't have both COUNT and UNTIL
+ //"FREQ=DAILY;UNTIL=19970829T021400e", // invalid date
+ };
+
+ /**
+ * Simple test of good/bad rules.
+ */
+ @SmallTest
+ public void testBasicParse() {
+ for (String rule : GOOD_RRULES) {
+ EventRecurrence recur = new EventRecurrence();
+ recur.parse(rule);
+ }
+
+ for (String rule : BAD_RRULES) {
+ EventRecurrence recur = new EventRecurrence();
+ boolean didThrow = false;
+
+ try {
+ recur.parse(rule);
+ } catch (InvalidFormatException ife) {
+ didThrow = true;
+ }
+
+ assertTrue("Expected throw on " + rule, didThrow);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index aedfbad..2ed7c52 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -95,7 +95,7 @@
private WebView mWebView;
/** Used for caching the default bindings so they can be restored. */
- private String mDefaultKeyBindings;
+ private static String sDefaultKeyBindings;
/** The received selection string for assertion checking. */
private static String sReceivedSelectionString = SELECTION_STRING_UNKNOWN;
@@ -1696,7 +1696,7 @@
*/
private void injectTestWebContentKeyBindings() {
ContentResolver contentResolver = getActivity().getContentResolver();
- mDefaultKeyBindings = Settings.Secure.getString(contentResolver,
+ sDefaultKeyBindings = Settings.Secure.getString(contentResolver,
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS);
Settings.Secure.putString(contentResolver,
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, TEST_KEY_DINDINGS);
@@ -1708,7 +1708,7 @@
private void restoreDefaultWebContentKeyBindings() {
Settings.Secure.putString(getActivity().getContentResolver(),
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
- mDefaultKeyBindings);
+ sDefaultKeyBindings);
}
/**
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index d8d145c..a37f1a3 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -22,6 +22,7 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.GetChars;
+import android.view.View;
import android.widget.TextView;
/**
@@ -58,4 +59,122 @@
assertEquals('o', c2[4]);
assertEquals('\0', c2[5]);
}
+
+ @SmallTest
+ public void testTextDirectionDefault() {
+ TextView tv = new TextView(mContext);
+ assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+ }
+
+ @SmallTest
+ public void testSetGetTextDirection() {
+ TextView tv = new TextView(mContext);
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
+ }
+
+ @SmallTest
+ public void testGetResolvedTextDirectionLtr() {
+ TextView tv = new TextView(mContext);
+ tv.setText("this is a test");
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+ }
+
+ @SmallTest
+ public void testGetResolvedTextDirectionLtrWithInheritance() {
+ LinearLayout ll = new LinearLayout(mContext);
+ ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+ TextView tv = new TextView(mContext);
+ tv.setText("this is a test");
+ ll.addView(tv);
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+ }
+
+ @SmallTest
+ public void testGetResolvedTextDirectionRtl() {
+ TextView tv = new TextView(mContext);
+ tv.setText("\u05DD\u05DE"); // hebrew
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+ }
+
+ @SmallTest
+ public void testGetResolvedTextDirectionRtlWithInheritance() {
+ LinearLayout ll = new LinearLayout(mContext);
+ ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+ TextView tv = new TextView(mContext);
+ tv.setText("\u05DD\u05DE"); // hebrew
+ ll.addView(tv);
+
+ tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+ assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+ tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+ assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java b/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java
deleted file mode 100644
index 36dee70..0000000
--- a/core/tests/coretests/src/com/android/internal/util/HanziToPinyinTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.util;
-
-import java.text.Collator;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Locale;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import com.android.internal.util.HanziToPinyin;
-import com.android.internal.util.HanziToPinyin.Token;
-
-import junit.framework.TestCase;
-
-public class HanziToPinyinTest extends TestCase {
- private final static String ONE_HANZI = "\u675C";
- private final static String TWO_HANZI = "\u675C\u9D51";
- private final static String ASSIC = "test";
- private final static String ONE_UNKNOWN = "\uFF71";
- private final static String MISC = "test\u675C Test with space\uFF71\uFF71\u675C";
-
- @SmallTest
- public void testGetToken() throws Exception {
- if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
- return;
- }
- ArrayList<Token> tokens = HanziToPinyin.getInstance().get(ONE_HANZI);
- assertEquals(tokens.size(), 1);
- assertEquals(tokens.get(0).type, Token.PINYIN);
- assertTrue(tokens.get(0).target.equalsIgnoreCase("DU"));
-
- tokens = HanziToPinyin.getInstance().get(TWO_HANZI);
- assertEquals(tokens.size(), 2);
- assertEquals(tokens.get(0).type, Token.PINYIN);
- assertEquals(tokens.get(1).type, Token.PINYIN);
- assertTrue(tokens.get(0).target.equalsIgnoreCase("DU"));
- assertTrue(tokens.get(1).target.equalsIgnoreCase("JUAN"));
-
- tokens = HanziToPinyin.getInstance().get(ASSIC);
- assertEquals(tokens.size(), 1);
- assertEquals(tokens.get(0).type, Token.LATIN);
-
- tokens = HanziToPinyin.getInstance().get(ONE_UNKNOWN);
- assertEquals(tokens.size(), 1);
- assertEquals(tokens.get(0).type, Token.UNKNOWN);
-
- tokens = HanziToPinyin.getInstance().get(MISC);
- assertEquals(tokens.size(), 7);
- assertEquals(tokens.get(0).type, Token.LATIN);
- assertEquals(tokens.get(1).type, Token.PINYIN);
- assertEquals(tokens.get(2).type, Token.LATIN);
- assertEquals(tokens.get(3).type, Token.LATIN);
- assertEquals(tokens.get(4).type, Token.LATIN);
- assertEquals(tokens.get(5).type, Token.UNKNOWN);
- assertEquals(tokens.get(6).type, Token.PINYIN);
- }
-}
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
new file mode 100644
index 0000000..be2e6bf
--- /dev/null
+++ b/core/tests/notificationtests/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := NotificationStressTests
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/notificationtests/AndroidManifest.xml b/core/tests/notificationtests/AndroidManifest.xml
new file mode 100644
index 0000000..51e530a
--- /dev/null
+++ b/core/tests/notificationtests/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.notification.tests" >
+
+ <application >
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.notification.tests"
+ android:label="Notification Stress Tests" />
+
+</manifest>
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
new file mode 100644
index 0000000..52ea1c4
--- /dev/null
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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 android.app;
+
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.test.RepetitiveTest;
+import android.test.TimedTest;
+
+import java.util.Random;
+
+/**
+ * Test which spams notification manager with a large number of notifications, for both stress and
+ * performance testing.
+ */
+public class NotificationStressTest extends InstrumentationTestCase {
+
+ private static final int NUM_ITERATIONS = 200;
+ private static final int[] ICONS = new int[] {
+ android.R.drawable.stat_notify_call_mute,
+ android.R.drawable.stat_notify_chat,
+ android.R.drawable.stat_notify_error,
+ android.R.drawable.stat_notify_missed_call,
+ android.R.drawable.stat_notify_more,
+ android.R.drawable.stat_notify_sdcard,
+ android.R.drawable.stat_notify_sdcard_prepare,
+ android.R.drawable.stat_notify_sdcard_usb,
+ android.R.drawable.stat_notify_sync,
+ android.R.drawable.stat_notify_sync_noanim,
+ android.R.drawable.stat_notify_voicemail,
+ };
+
+ private final Random mRandom = new Random();
+ private Context mContext;
+ private NotificationManager mNotificationManager;
+ private int notifyId = 0;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+ mNotificationManager = (NotificationManager) mContext.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mNotificationManager.cancelAll();
+ }
+
+ @RepetitiveTest(numIterations=NUM_ITERATIONS)
+ public void testNotificationStress() {
+ // Cancel one of every five notifications to vary load on notification manager
+ if (notifyId % 5 == 4) {
+ mNotificationManager.cancel(notifyId - 4);
+ }
+ sendNotification(notifyId++, "testNotificationStressNotify");
+ }
+
+ private void sendNotification(int id, CharSequence text) {
+ // Create "typical" notification with random icon
+ Notification notification = new Notification(ICONS[mRandom.nextInt(ICONS.length)], text,
+ System.currentTimeMillis());
+ // Fill in arbitrary content
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
+ PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+ CharSequence title = text + " " + id;
+ CharSequence subtitle = String.valueOf(System.currentTimeMillis());
+ notification.setLatestEventInfo(mContext, title, subtitle, pendingIntent);
+ mNotificationManager.notify(id, notification);
+ SystemClock.sleep(10);
+ }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index b9c0d80..0b8d40f 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -84,6 +84,16 @@
<group gid="diag" />
</permission>
+ <!-- Group that can read detailed network usage statistics -->
+ <permission name="android.permission.READ_NETWORK_USAGE_HISTORY">
+ <group gid="net_bw_stats" />
+ </permission>
+
+ <!-- Group that can modify how network statistics are accounted -->
+ <permission name="android.permission.MODIFY_NETWORK_ACCOUNTING">
+ <group gid="net_bw_acct" />
+ </permission>
+
<!-- ================================================================== -->
<!-- ================================================================== -->
<!-- ================================================================== -->
diff --git a/data/fonts/DroidSansEthiopic-Bold.ttf b/data/fonts/DroidSansEthiopic-Bold.ttf
new file mode 100644
index 0000000..e06cac2
--- /dev/null
+++ b/data/fonts/DroidSansEthiopic-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansEthiopic-Regular.ttf b/data/fonts/DroidSansEthiopic-Regular.ttf
new file mode 100644
index 0000000..0adcbbe
--- /dev/null
+++ b/data/fonts/DroidSansEthiopic-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Bold.ttf b/data/fonts/DroidSansHebrew-Bold.ttf
new file mode 100644
index 0000000..c1acb38
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew-Regular.ttf b/data/fonts/DroidSansHebrew-Regular.ttf
new file mode 100644
index 0000000..af6a58d
--- /dev/null
+++ b/data/fonts/DroidSansHebrew-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansHebrew.ttf b/data/fonts/DroidSansHebrew.ttf
deleted file mode 100644
index 8d77e3e..0000000
--- a/data/fonts/DroidSansHebrew.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 692ce34..d222c0b 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -18,7 +18,8 @@
frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \
frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \
frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
- frameworks/base/data/fonts/DroidSansHebrew.ttf:system/fonts/DroidSansHebrew.ttf \
+ frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
+ frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
frameworks/base/data/fonts/DroidSansThai.ttf:system/fonts/DroidSansThai.ttf \
frameworks/base/data/fonts/DroidSerif-Regular.ttf:system/fonts/DroidSerif-Regular.ttf \
frameworks/base/data/fonts/DroidSerif-Bold.ttf:system/fonts/DroidSerif-Bold.ttf \
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index 3127e10..cb5a0b6 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -145,6 +145,9 @@
<td>Kyocera</td>
<td><code>0482</code></td></tr>
<tr>
+ <td>Lenevo</td>
+ <td><code>17EF</code></td></tr>
+ <tr>
<td>LG</td>
<td><code>1004</code></td></tr>
<tr>
diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
index c0795d7..499b610 100644
--- a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
+++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
@@ -125,7 +125,7 @@
device.startActivity(component=runComponent)
# Presses the Menu button
-device.press('KEYCODE_MENU','DOWN_AND_UP')
+device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP)
# Takes a screenshot
result = device.takeSnapshot()
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 55d711f..3ec174e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -222,7 +222,8 @@
<li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html"><receiver></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html"><service></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html"><supports-gl-texture></a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a></li> <!-- ##api level 4## -->
+ <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a>
+ <span class="new">updated</span></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html"><uses-feature></a></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html"><uses-library></a></li>
@@ -256,7 +257,7 @@
<div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
<span class="en">RenderScript</span>
</a>
- <span class="new-child">new!</span></div>
+ <span class="new">new!</span></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
<span class="en">3D Graphics</span>
@@ -270,8 +271,8 @@
</li>
<li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
- <span class="en">Audio and Video</span>
- </a></li>
+ <span class="en">Media</span>
+ </a><span class="new">updated</span></li>
<li>
<a href="<?cs var:toroot ?>guide/topics/clipboard/copy-paste.html">
<span class="en">Copy and Paste</span>
@@ -302,11 +303,13 @@
</li> -->
<!--<li><a style="color:gray;">Localization</a></li> -->
<li><a href="<?cs var:toroot ?>guide/topics/appwidgets/index.html">
- <span class="en">App Widgets</span>
- </a></li>
+ <span class="en">App Widgets</span></a>
+ <span class="new">updated</span>
+ </li>
<li><a href="<?cs var:toroot?>guide/topics/wireless/bluetooth.html">
- <span class="en">Bluetooth</span>
- </a></li>
+ <span class="en">Bluetooth</span></a>
+ <span class="new">updated</span>
+ </li>
<li><a href="<?cs var:toroot?>guide/topics/nfc/index.html">
<span class="en">Near Field Communication</span>
</a></li>
@@ -337,8 +340,8 @@
</ul>
</li>
<li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
- <span class="en">Device Administration</span>
- </a>
+ <span class="en">Device Administration</span></a>
+ <span class="new">updated</span>
</li>
<li class="toggle-list">
<div>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index e589292..78b5b51 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -213,7 +213,7 @@
<p class="note"><strong>Note:</strong> To make your app widget portable across
devices, your app widget's minimum size should never be larger than 4 x 4 cells.
See the <a
-href="{@docRoot}guide/practices/ui_guidelines/widget_design.htmll#sizes">App
+href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#sizes">App
Widget Design Guidelines</a> for more discussion of Home screen cell sizes.</p>
</li>
<li>The <code>updatePeriodMillis</code> attribute defines how often the App
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
index 5cc1b45..cb453da 100644
--- a/docs/html/guide/topics/fundamentals/activities.jd
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -145,7 +145,7 @@
<h3 id="Declaring">Declaring the activity in the manifest</h3>
<p>You must declare your activity in the manifest file in order for it to
-be accessible to the system. To decalare your activity, open your manifest file and add an <a
+be accessible to the system. To declare your activity, open your manifest file and add an <a
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
as a child of the <a
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
@@ -163,9 +163,16 @@
<p>There are several other attributes that you can include in this element, to define properties
such as the label for the activity, an icon for the activity, or a theme to style the activity's
-UI. See the <a
+UI. The <a href="{@docRoot}guide/topics/manifest/activity-element.html#nm">{@code android:name}</a>
+attribute is the only required attribute—it specifies the class name of the activity. Once
+you publish your application, you should not change this name, because if you do, you might break
+some functionality, such as application shortcuts (read the blog post, <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).</p>
+
+<p>See the <a
href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element
-reference for more information about available attributes.</p>
+reference for more information about declaring your activity in the manifest.</p>
<h4>Using intent filters</h4>
diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd
index 468a417..9c38897 100644
--- a/docs/html/guide/topics/fundamentals/services.jd
+++ b/docs/html/guide/topics/fundamentals/services.jd
@@ -203,7 +203,7 @@
<p>Like activities (and other components), you must declare all services in your application's
manifest file.</p>
-<p>To decalare your service, add a <a
+<p>To declare your service, add a <a
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
as a child of the <a
href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a>
@@ -222,9 +222,17 @@
<p>There are other attributes you can include in the <a
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to
define properties such as permissions required to start the service and the process in
-which the service should run. See the <a
+which the service should run. The <a
+href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
+attribute is the only required attribute—it specifies the class name of the service. Once
+you publish your application, you should not change this name, because if you do, you might break
+some functionality where explicit intents are used to reference your service (read the blog post, <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things
+That Cannot Change</a>).
+
+<p>See the <a
href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element
-reference for more information.</p>
+reference for more information about declaring your service in the manifest.</p>
<p>Just like an activity, a service can define intent filters that allow other components to
invoke the service using implicit intents. By declaring intent filters, components
@@ -670,7 +678,7 @@
either stopped or removed from the foreground.</p>
<p>For example, a music player that plays music from a service should be set to run in the
-foreground, because the user it explicitly aware
+foreground, because the user is explicitly aware
of its operation. The notification in the status bar might indicate the current song and allow
the user to launch an activity to interact with the music player.</p>
diff --git a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
index 072488c..216420c 100644
--- a/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
+++ b/docs/html/guide/topics/fundamentals/tasks-and-back-stack.jd
@@ -10,7 +10,7 @@
<li>All activities belong to a task</li>
<li>A task contains a collection of activities in the order in which the user interacts with
them</li>
- <li>Tasks can move to the background and retain the state of each activity in order for the user
+ <li>Tasks can move to the background and retain the state of each activity in order for users
to perform other tasks without losing their work</li>
</ul>
@@ -306,7 +306,7 @@
and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D.
If D has the default {@code "standard"} launch mode, a new instance of the class is launched and the
stack becomes A-B-C-D-D. However, if D's launch mode is {@code "singleTop"}, the existing instance
-of D is deliverd the intent through {@link
+of D receives the intent through {@link
android.app.Activity#onNewIntent onNewIntent()}, because it's at the top of the stack—the
stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new
instance of B is added to the stack, even if its launch mode is {@code "singleTop"}.</p>
@@ -363,7 +363,7 @@
<p class="note"><strong>Note:</strong> The behaviors that you specify for your activity with the <a
href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a> attribute
-can be overriden by flags included with the intent that start your activity, as discussed in the
+can be overridden by flags included with the intent that start your activity, as discussed in the
next section.</p>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index c910686..3486212 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -507,6 +507,10 @@
package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code>
element.
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
<p>
There is no default. The name must be specified.
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index 598e88f..d737a67 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -47,12 +47,15 @@
to "{@code http://schemas.android.com/apk/res/android}".</dd>
<dt><a name="package"></a>{@code package}</dt>
-<dd>A full Java package name for the application. The name should
+<dd>A full Java-language-style package name for the application. The name should
be unique. The name may contain uppercase or lowercase letters ('A'
through 'Z'), numbers, and underscores ('_'). However, individual
-package name parts may only start with letters. For example, applications
-published by Google could have names in the form
-<code>com.google.app.<i>application_name</i></code>.
+package name parts may only start with letters.
+
+<p>To avoid conflicts with other developers, you should use Internet domain ownership as the
+basis for your package names (in reverse). For example, applications published by Google start with
+<code>com.google</code>. You should also never use the <code>com.example</code> namespace when
+publishing your applications.</p>
<p>
The package name serves as a unique identifier for the application.
@@ -66,6 +69,12 @@
element's
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">taskAffinity</a></code> attribute).
</p>
+
+ <p class="caution"><strong>Caution:</strong> Once you publish your application, you
+<strong>cannot change the package name</strong>. The package name defines your application's
+identity, so if you change it, then it is considered to be a different application and users of
+the previous version cannot update to the new version.</p>
+
</dd>
<dt><a name="uid"></a>{@code android:sharedUserId}</dt>
diff --git a/docs/html/guide/topics/manifest/receiver-element.jd b/docs/html/guide/topics/manifest/receiver-element.jd
index 7012c0f..8416c0c 100644
--- a/docs/html/guide/topics/manifest/receiver-element.jd
+++ b/docs/html/guide/topics/manifest/receiver-element.jd
@@ -122,6 +122,11 @@
"{@code . ReportReceiver}"), it is appended to the package name specified in
the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code> element.
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
+
<p>
There is no default. The name must be specified.
</p></dd>
diff --git a/docs/html/guide/topics/manifest/service-element.jd b/docs/html/guide/topics/manifest/service-element.jd
index d9a81b3..82d1f6a 100644
--- a/docs/html/guide/topics/manifest/service-element.jd
+++ b/docs/html/guide/topics/manifest/service-element.jd
@@ -6,7 +6,7 @@
<dl class="xml">
<dt>syntax:</dt>
<dd><pre class="stx"><service android:<a href="#enabled">enabled</a>=["true" | "false"]
- android:<a href="#exported">exported[</a>="true" | "false"]
+ android:<a href="#exported">exported</a>=["true" | "false"]
android:<a href="#icon">icon</a>="<i>drawable resource</i>"
android:<a href="#label">label</a>="<i>string resource</i>"
android:<a href="#nm">name</a>="<i>string</i>"
@@ -121,6 +121,11 @@
it is appended to the package name specified in the
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code> element.
+<p>Once you publish your application, you <a
+href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">should not
+change this name</a> (unless you've set <code><a
+href="#exported">android:exported</a>="false"</code>).</p>
+
<p>
There is no default. The name must be specified.
</p></dd>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index ee99a37..605a2bb 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,12 +8,15 @@
<dt>syntax:</dt>
<dd>
<pre class="stx">
-<supports-screens android:<a href="#resizeable">resizeable</a>=["true" | "false"]
- android:<a href="#small">smallScreens</a>=["true" | "false"]
- android:<a href="#normal">normalScreens</a>=["true" | "false"]
- android:<a href="#large">largeScreens</a>=["true" | "false"]
+<supports-screens android:<a href="#requiresSmallest">requiresSmallestWidthDp</a>="<em>integer</em>"
+ android:<a href="#compatibleWidth">compatibleWidthLimitDp</a>="<em>integer</em>"
+ android:<a href="#largestWidth">largestWidthLimitDp</a>="<em>integer</em>"
+ android:<a href="#resizeable">resizeable</a>=["true"| "false"]
+ android:<a href="#small">smallScreens</a>=["true" | "false"]
+ android:<a href="#normal">normalScreens</a>=["true" | "false"]
+ android:<a href="#large">largeScreens</a>=["true" | "false"]
android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
- android:<a href="#any">anyDensity</a>=["true" | "false"] />
+ android:<a href="#any">anyDensity</a>=["true" | "false"] />
</pre>
</dd>
@@ -21,36 +24,37 @@
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
<dt>description:</dt>
-<dd>Lets you specify the screen dimensions the
-application supports. By default, a modern application (using API Level 4 or higher) supports all
-screen sizes; older applications are assumed to support only the "normal" screen size. Screen
-size is determined as the available pixels to an application after density scaling has been
-applied. (Note that screen size is a separate axis from screen density.)
+<dd>Lets you specify the screen sizes your application supports and enable screen
+compatibility mode for screens larger than what your application supports. By default, a modern
+application (using API Level 4 or higher) supports all screen sizes; older applications are assumed
+to support only the "normal" screen size. Screen size is determined by the number of pixels on the
+screen after the system accounts for screen density scaling.
-<p>An application "supports" a given screen size if it fills the entire screen and works as
-expected. By default, the system will resize your application to fill the screen, if you have set
+<p>An application "supports" a given screen size if it resizes properly to fill the entire screen.
+By default, the system resizes your application UI to fill the screen if you have set
either <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
minSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-targetSdkVersion}</a> to {@code "4"} or higher. Resizing works well for most applications and
-you don't have to do any extra work to make your application work on larger screens.</p>
+targetSdkVersion}</a> to {@code "4"} or higher. Normal resizing works well for most applications and
+you don't have to do any extra work to make your application work on screens larger than a
+handset device.</p>
-<p>In addition to allowing the system to resize your application, you can add additional support
-for different screen sizes by providing <a
+<p>In addition to allowing the system to resize your application to fit the current screen, you can
+optimize your UI for different screen sizes by providing <a
href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
layout resources</a> for different sizes. For instance, you might want to modify the layout
of an activity when it is on a tablet or similar device that has an <em>xlarge</em> screen.</p>
-<p>If your application does not support <em>large</em> or <em>xlarge</em> screens, then you should
-declare that it is not resizeable by setting <a href="#resizeable">{@code android:resizeable}</a> to
-{@code "false"}, so that the system will not resize your application on larger screens.</p>
+<p>However, if your application does not work well when resized to fit different screen sizes,
+you can use the attributes of the {@code <supports-screens>} element to control whether
+your application should be distributed to smaller screens or have its UI scaled up to fit larger
+screens using the system's screen compatibility mode. When you have not designed for larger screen
+sizes and the normal resizing does not achieve the appropriate results, <em>screen compatibility
+mode</em> will scale your UI by emulating a <em>normal</em> size screen and then zooming in on it so
+that it fills the entire screen—thus achieving the same layout as a normal handset device on
+the large screen (but this usually causes pixelation and blurring of your UI).</p>
-<p>If your application does not support <em>small</em> screens, then
-there isn't much the system can do to make the application work well on a smaller screen, so
-external services (such as Android Market) should not allow users to install the application on such
-screens.</p>
-
-
-<p>For more information, see
+<p>For more information about how to properly support different screen sizes so that you can avoid
+using screen compatibility mode, read
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
@@ -59,6 +63,74 @@
<dd>
<dl class="attr">
+ <dt id="requiresSmallest">{@code android:requiresSmallestWidthDp}</dt>
+ <dd>This attribute specifies the minimum "smallest screen width" with which your
+application is compatible. In order for a device to be considered compatible with your
+application, the shortest side of the available screen space must be equal to or greater than this
+value.
+<p>The width against which your value is compared takes into account screen decorations and system
+UI. For example, if the device has some persistent UI elements on the left or right edge of the
+display, the system declares the device's available width as one that is smaller than the actual
+screen size, accounting for these UI elements because those are screen pixels not available for your
+UI. Thus, the value you use should be the actual smallest width required by your layout.</p>
+<p>If your application properly resizes for smaller screen sizes (down to the
+<em>small</em> size or a minimum width of 320dp), you do
+not need to use this attribute. Otherwise, you should use a value for this attribute that
+matches the smallest value used by your application for the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+smallest screen width qualifier</a> ({@code sw<N>dp}).</p>
+
+<p>For example, a typical handset screen has a minimum width of 320dp, a 7" tablet has a minimum
+width of 600dp, and a 10" tablet has a minimum width of 720dp. If the smallest available screen
+width on a device is less than the value you supply here, then the application is considered
+incompatible with that
+device. External services such as Android Market use this to determine whether a device
+is compatible with your application and prevent incompatible devices from installing it.</p>
+<p>Beginning with Android 3.2 (API level 13), using this attribute is the preferred way to
+specify the minimum screen size your application requires, instead of using the other attributes
+for small, normal, large, and xlarge screens. The advantage of using this attribute is that you
+have more control over exactly how much screen space your application needs at a minimum in order
+to properly display its UI, rather than relying on the generalized size groups.</p>
+<p>This attribute has no default value. If this attribute is not specified, then any of the old
+<code><a href="#small">smallScreens</a></code>, <code><a href="#normal">normalScreens</a></code>,
+<code><a href="#large">largeScreens</a></code>, or <code><a href="#xlarge">xlargeScreens</a></code>
+attributes are used instead to determine the smallest screen required.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
+ <dt id="compatibleWidth">{@code android:compatibleWidthLimitDp}</dt>
+ <dd>This attribute allows you to enable screen compatibility mode as a user-optional feature by
+specifying the maximum "smallest screen width" for which your application is designed. If the value
+you supply here is less than the shortest side of the available screen space, users can still
+install your application, but are offered to run it in screen compatibility mode. By default, screen
+compatibility mode is disabled and your layout is resized to fit the screen as usual, but a
+button is available in the system bar that allows the user to toggle screen compatibility mode on
+and off.
+ <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:compatibleWidthLimitDp} is larger than 320.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
+ <dt id="largestWidth">{@code android:largestWidthLimitDp}</dt>
+ <dd>This attribute allows you to force enable screen compatibility mode by specifying the maximum
+"smallest screen width" for which your application is designed. If the value you supply here is less
+than the shortest side of the available screen space, the application runs in screen
+compatibility mode with no way for the user to disable it.
+ <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute. Otherwise, you should first consider using the <a
+href="#compatibleWidth">{@code android:compatibleWidthLimitDp}</a> attribute. You should use the
+{@code android:largestWidthLimitDp} attribute only when your application is functionally broken when
+resized for larger screens and screen compatibility mode is the only way that users should use
+your application.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:largestWidthLimitDp} is larger than 320.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
<dt><a name="resizeable"></a>{@code android:resizeable}</dt>
<dd>Indicates whether the application is resizeable for different screen sizes. This attribute is
true, by default, if you have set either <a
@@ -75,6 +147,7 @@
application does not work well on larger screens, follow the guide to <a
href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to enable
additional screen support.</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
@@ -91,6 +164,7 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="normal"></a>{@code android:normalScreens}</dt>
@@ -99,12 +173,13 @@
screen, but WQVGA low density and WVGA high density are also
considered to be normal. This attribute is "true" by default,
and applications currently should leave it that way.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="large"></a>{@code android:largeScreens}</dt>
<dd>Indicates whether the application supports larger screen form-factors.
A large screen is defined as a screen that is significantly larger
- than a "normal" phone screen, and thus might require some special care
+ than a "normal" handset screen, and thus might require some special care
on the application's part to make good use of it, though it may rely on resizing by the
system to fill the screen. If the application has set either <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
@@ -112,6 +187,7 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
@@ -125,7 +201,8 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
- <p>This attribute was introduced in API Level 9.</p>
+ <p>This attribute was introduced in API level 9.</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="any"></a>{@code android:anyDensity}</dt>
@@ -142,6 +219,7 @@
down application assets by a factor of 0.75 (low dpi screens) or scale them up by a factor of 1.5
(high dpi screens), when you don't provide alternative resources for a specifc screen density. The
screen density is expressed as dots-per-inch (dpi).</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
diff --git a/docs/html/guide/topics/media/images/notification1.png b/docs/html/guide/topics/media/images/notification1.png
new file mode 100644
index 0000000..9b01971
--- /dev/null
+++ b/docs/html/guide/topics/media/images/notification1.png
Binary files differ
diff --git a/docs/html/guide/topics/media/images/notification2.png b/docs/html/guide/topics/media/images/notification2.png
new file mode 100644
index 0000000..488648e
--- /dev/null
+++ b/docs/html/guide/topics/media/images/notification2.png
Binary files differ
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index b6d1629..06e6208 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -1,4 +1,4 @@
-page.title=Audio and Video
+page.title=Media
@jd:body
<div id="qv-wrapper">
@@ -6,30 +6,44 @@
<h2>Quickview</h2>
<ul>
-<li>Audio playback and record</li>
-<li>Video playback</li>
-<li>Handles data from raw resources, files, streams</li>
-<li>Built-in codecs for a variety of media. See <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
+<li>MediaPlayer APIs allow you to play and record media</li>
+<li>You can handle data from raw resources, files, and streams</li>
+<li>The platform supports a variety of media formats. See <a
+href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media Formats</a></li>
</ul>
<h2>In this document</h2>
<ol>
-<li><a href="#playback">Audio and Video Playback</a>
- <ol>
- <li><a href="#playraw">Playing from a Raw Resource</li>
- <li><a href="#playfile">Playing from a File or Stream</li>
- <li><a href="#jet">Playing JET Content</li>
- </ol>
+<li><a href="#mediaplayer">Using MediaPlayer</a>
+ <ol>
+ <li><a href='#preparingasync'>Asynchronous Preparation</a></li>
+ <li><a href='#managestate'>Managing State</a></li>
+ <li><a href='#releaseplayer'>Releasing the MediaPlayer</a></li>
+ </ol>
</li>
-<li><a href="#capture">Audio Capture</a></li>
+<li><a href="#mpandservices">Using a Service with MediaPlayer</a>
+ <ol>
+ <li><a href="#asyncprepare">Running asynchronously</a></li>
+ <li><a href="#asyncerror">Handling asynchronous errors</a></li>
+ <li><a href="#wakelocks">Using wake locks</a></li>
+ <li><a href="#foregroundserv">Running as a foreground service</a></li>
+ <li><a href="#audiofocus">Handling audio focus</a></li>
+ <li><a href="#cleanup">Performing cleanup</a></li>
+ </ol>
+</li>
+<li><a href="#noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</a>
+<li><a href="#viacontentresolver">Retrieving Media from a Content Resolver</a>
+<li><a href="#jetcontent">Playing JET content</a>
+<li><a href="#audiocapture">Performing Audio Capture</a>
</ol>
<h2>Key classes</h2>
<ol>
-<li>{@link android.media.MediaPlayer MediaPlayer}</li>
-<li>{@link android.media.MediaRecorder MediaRecorder}</li>
-<li>{@link android.media.JetPlayer JetPlayer}</li>
-<li>{@link android.media.SoundPool SoundPool}</li>
+<li>{@link android.media.MediaPlayer}</li>
+<li>{@link android.media.MediaRecorder}</li>
+<li>{@link android.media.AudioManager}</li>
+<li>{@link android.media.JetPlayer}</li>
+<li>{@link android.media.SoundPool}</li>
</ol>
<h2>See also</h2>
@@ -41,129 +55,729 @@
</div>
</div>
-<p>The Android platform offers built-in encoding/decoding for a variety of
-common media types, so that you can easily integrate audio, video, and images into your
-applications. Accessing the platform's media capabilities is fairly straightforward
-— you do so using the same intents and activities mechanism that the rest of
-Android uses.</p>
+<p>The Android multimedia framework includes support for encoding and decoding a
+variety of common media types, so that you can easily integrate audio,
+video and images into your applications. You can play audio or video from media files stored in your
+application's resources (raw resources), from standalone files in the filesystem, or from a data
+stream arriving over a network connection, all using {@link android.media.MediaPlayer} APIs.</p>
-<p>Android lets you play audio and video from several types of data sources. You
-can play audio or video from media files stored in the application's resources
-(raw resources), from standalone files in the filesystem, or from a data stream
-arriving over a network connection. To play audio or video from your
-application, use the {@link android.media.MediaPlayer} class.</p>
+<p>You can also record audio and video using the {@link android.media.MediaRecorder} APIs if
+supported by the device hardware. Note that the emulator doesn't have hardware to capture audio or
+video, but actual mobile devices are likely to provide these capabilities.</p>
-<p>The platform also lets you record audio and video, where supported by the
-mobile device hardware. To record audio or video, use the {@link
-android.media.MediaRecorder} class. Note that the emulator doesn't have hardware
-to capture audio or video, but actual mobile devices are likely to provide these
-capabilities, accessible through the MediaRecorder class. </p>
+<p>This document shows you how to write a media-playing application that interacts with the user and
+the system in order to obtain good performance and a pleasant user experience.</p>
-<p>For a list of media formats for which Android offers built-in support,
-see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Media
-Formats</a> appendix. </p>
+<p class="note"><strong>Note:</strong> You can play back the audio data only to the standard output
+device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound
+files in the conversation audio during a call.</p>
-<h2 id="playback">Audio and Video Playback</h2>
-<p>Media can be played from anywhere: from a raw resource, from a file from the system,
-or from an available network (URL).</p>
-
-<p>You can play back the audio data only to the standard
-output device; currently, that is the mobile device speaker or Bluetooth headset. You
-cannot play sound files in the conversation audio. </p>
-<h3 id="playraw">Playing from a Raw Resource</h3>
-<p>Perhaps the most common thing to want to do is play back media (notably sound)
-within your own applications. Doing this is easy:</p>
-<ol>
- <li>Put the sound (or other media resource) file into the <code>res/raw</code>
- folder of your project, where the Eclipse plugin (or aapt) will find it and
- make it into a resource that can be referenced from your R class</li>
- <li>Create an instance of <code>MediaPlayer</code>, referencing that resource using
- {@link android.media.MediaPlayer#create MediaPlayer.create}, and then call
- {@link android.media.MediaPlayer#start() start()} on the instance:</li>
-</ol>
-<pre>
- MediaPlayer mp = MediaPlayer.create(context, R.raw.sound_file_1);
- mp.start();
+<h2 id="mediaplayer">Using MediaPlayer</h2>
+
+<p>One of the most important components of the media framework is the
+{@link android.media.MediaPlayer MediaPlayer}
+class. An object of this class can fetch, decode, and play both audio and video
+with minimal setup. It supports several different media sources such as:
+<ul>
+ <li>Local resources</li>
+ <li>Internal URIs, such as one you might obtain from a Content Resolver</li>
+ <li>External URLs (streaming)</li>
+</ul>
+</p>
+
+<p>For a list of media formats that Android supports,
+see the <a href="{@docRoot}guide/appendix/media-formats.html">Android Supported Media
+Formats</a> document. </p>
+
+<p>Here is an example
+of how to play audio that's available as a local raw resource (saved in your application's
+{@code res/raw/} directory):</p>
+
+<pre>MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
+mediaPlayer.start(); // no need to call prepare(); create() does that for you
</pre>
-<p>To stop playback, call {@link android.media.MediaPlayer#stop() stop()}. If
-you wish to later replay the media, then you must
-{@link android.media.MediaPlayer#reset() reset()} and
-{@link android.media.MediaPlayer#prepare() prepare()} the MediaPlayer object
-before calling {@link android.media.MediaPlayer#start() start()} again.
-(<code>create()</code> calls <code>prepare()</code> the first time.)</p>
-<p>To pause playback, call {@link android.media.MediaPlayer#pause() pause()}.
-Resume playback from where you paused with
-{@link android.media.MediaPlayer#start() start()}.</p>
-<h3 id="playfile">Playing from a File or Stream</h3>
-<p>You can play back media files from the filesystem or a web URL:</p>
-<ol>
- <li>Create an instance of the <code>MediaPlayer</code> using <code>new</code></li>
- <li>Call {@link android.media.MediaPlayer#setDataSource setDataSource()}
- with a String containing the path (local filesystem or URL)
- to the file you want to play</li>
- <li>First {@link android.media.MediaPlayer#prepare prepare()} then
- {@link android.media.MediaPlayer#start() start()} on the instance:</li>
-</ol>
-<pre>
- MediaPlayer mp = new MediaPlayer();
- mp.setDataSource(PATH_TO_FILE);
- mp.prepare();
- mp.start();
-</pre>
-<p>{@link android.media.MediaPlayer#stop() stop()} and
-{@link android.media.MediaPlayer#pause() pause()} work the same as discussed
-above.</p>
- <p class="note"><strong>Note:</strong>
- <code>IllegalArgumentException</code> and <code>IOException</code> either
- need to be caught or passed on when using <code>setDataSource()</code>, since
- the file you are referencing may not exist.</p>
+<p>In this case, a "raw" resource is a file that the system does not
+try to parse in any particular way. However, the content of this resource should not
+be raw audio. It should be a properly encoded and formatted media file in one
+of the supported formats.</p>
+
+<p>And here is how you might play from a URI available locally in the system
+(that you obtained through a Content Resolver, for instance):</p>
+
+<pre>Uri myUri = ....; // initialize Uri here
+MediaPlayer mediaPlayer = new MediaPlayer();
+mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mediaPlayer.setDataSource(getApplicationContext(), myUri);
+mediaPlayer.prepare();
+mediaPlayer.start();</pre>
+
+<p>Playing from a remote URL via HTTP streaming looks like this:</p>
+
+<pre>String url = "http://........"; // your URL here
+MediaPlayer mediaPlayer = new MediaPlayer();
+mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mediaPlayer.setDataSource(url);
+mediaPlayer.prepare(); // might take long! (for buffering, etc)
+mediaPlayer.start();</pre>
+
<p class="note"><strong>Note:</strong>
-If you're passing a URL to an online media file, the file must be capable of
+If you're passing a URL to stream an online media file, the file must be capable of
progressive download.</p>
-<h3 id="jet">Playing JET content</h3>
-<p>The Android platform includes a JET engine that lets you add interactive playback of JET audio content in your applications. You can create JET content for interactive playback using the JetCreator authoring application that ships with the SDK. To play and manage JET content from your application, use the {@link android.media.JetPlayer JetPlayer} class.</p>
+<p class="caution"><strong>Caution:</strong> You must either catch or pass
+{@link java.lang.IllegalArgumentException} and {@link java.io.IOException} when using
+{@link android.media.MediaPlayer#setDataSource setDataSource()}, because
+the file you are referencing might not exist.</p>
-<p>For a description of JET concepts and instructions on how to use the JetCreator authoring tool, see the <a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User Manual</a>. The tool is available fully-featured on the OS X and Windows platforms and the Linux version supports all the content creation features, but not the auditioning of the imported assets. </p>
+<h3 id='#preparingasync'>Asynchronous Preparation</h3>
-<p>Here's an example of how to set up JET playback from a .jet file stored on the SD card:</p>
+<p>Using {@link android.media.MediaPlayer MediaPlayer} can be straightforward in
+principle. However, it's important to keep in mind that a few more things are
+necessary to integrate it correctly with a typical Android application. For
+example, the call to {@link android.media.MediaPlayer#prepare prepare()} can
+take a long time to execute, because
+it might involve fetching and decoding media data. So, as is the case with any
+method that may take long to execute, you should <strong>never call it from your
+application's UI thread</strong>. Doing that will cause the UI to hang until the method returns,
+which is a very bad user experience and can cause an ANR (Application Not Responding) error. Even if
+you expect your resource to load quickly, remember that anything that takes more than a tenth
+of a second to respond in the UI will cause a noticeable pause and will give
+the user the impression that your application is slow.</p>
+
+<p>To avoid hanging your UI thread, spawn another thread to
+prepare the {@link android.media.MediaPlayer} and notify the main thread when done. However, while
+you could write the threading logic
+yourself, this pattern is so common when using {@link android.media.MediaPlayer} that the framework
+supplies a convenient way to accomplish this task by using the
+{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. This method
+starts preparing the media in the background and returns immediately. When the media
+is done preparing, the {@link android.media.MediaPlayer.OnPreparedListener#onPrepared onPrepared()}
+method of the {@link android.media.MediaPlayer.OnPreparedListener
+MediaPlayer.OnPreparedListener}, configured through
+{@link android.media.MediaPlayer#setOnPreparedListener setOnPreparedListener()} is called.</p>
+
+<h3 id='#managestate'>Managing State</h3>
+
+<p>Another aspect of a {@link android.media.MediaPlayer} that you should keep in mind is
+that it's state-based. That is, the {@link android.media.MediaPlayer} has an internal state
+that you must always be aware of when writing your code, because certain operations
+are only valid when then player is in specific states. If you perform an operation while in the
+wrong state, the system may throw an exception or cause other undesireable behaviors.</p>
+
+<p>The documentation in the
+{@link android.media.MediaPlayer MediaPlayer} class shows a complete state diagram,
+that clarifies which methods move the {@link android.media.MediaPlayer} from one state to another.
+For example, when you create a new {@link android.media.MediaPlayer}, it is in the <em>Idle</em>
+state. At that point, you should initialize it by calling
+{@link android.media.MediaPlayer#setDataSource setDataSource()}, bringing it
+to the <em>Initialized</em> state. After that, you have to prepare it using either the
+{@link android.media.MediaPlayer#prepare prepare()} or
+{@link android.media.MediaPlayer#prepareAsync prepareAsync()} method. When
+the {@link android.media.MediaPlayer} is done preparing, it will then enter the <em>Prepared</em>
+state, which means you can call {@link android.media.MediaPlayer#start start()}
+to make it play the media. At that point, as the diagram illustrates,
+you can move between the <em>Started</em>, <em>Paused</em> and <em>PlaybackCompleted</em> states by
+calling such methods as
+{@link android.media.MediaPlayer#start start()},
+{@link android.media.MediaPlayer#pause pause()}, and
+{@link android.media.MediaPlayer#seekTo seekTo()},
+amongst others. When you
+call {@link android.media.MediaPlayer#stop stop()}, however, notice that you
+cannot call {@link android.media.MediaPlayer#start start()} again until you
+prepare the {@link android.media.MediaPlayer} again.</p>
+
+<p>Always keep <a href='{@docRoot}images/mediaplayer_state_diagram.gif'>the state diagram</a>
+in mind when writing code that interacts with a
+{@link android.media.MediaPlayer} object, because calling its methods from the wrong state is a
+common cause of bugs.</p>
+
+<h3 id='#releaseplayer'>Releasing the MediaPlayer</h3>
+
+<p>A {@link android.media.MediaPlayer MediaPlayer} can consume valuable
+system resources.
+Therefore, you should always take extra precautions to make sure you are not
+hanging on to a {@link android.media.MediaPlayer} instance longer than necessary. When you
+are done with it, you should always call
+{@link android.media.MediaPlayer#release release()} to make sure any
+system resources allocated to it are properly released. For example, if you are
+using a {@link android.media.MediaPlayer} and your activity receives a call to {@link
+android.app.Activity#onStop onStop()}, you must release the {@link android.media.MediaPlayer},
+because it
+makes little sense to hold on to it while your activity is not interacting with
+the user (unless you are playing media in the background, which is discussed in the next section).
+When your activity is resumed or restarted, of course, you need to
+create a new {@link android.media.MediaPlayer} and prepare it again before resuming playback.</p>
+
+<p>Here's how you should release and then nullify your {@link android.media.MediaPlayer}:</p>
+<pre>
+mediaPlayer.release();
+mediaPlayer = null;
+</pre>
+
+<p>As an example, consider the problems that could happen if you
+forgot to release the {@link android.media.MediaPlayer} when your activity is stopped, but create a
+new one when the activity starts again. As you may know, when the user changes the
+screen orientation (or changes the device configuration in another way),
+the system handles that by restarting the activity (by default), so you might quickly
+consume all of the system resources as the user
+rotates the device back and forth between portrait and landscape, because at each
+orientation change, you create a new {@link android.media.MediaPlayer} that you never
+release. (For more information about runtime restarts, see <a
+href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>.)</p>
+
+<p>You may be wondering what happens if you want to continue playing
+"background media" even when the user leaves your activity, much in the same
+way that the built-in Music application behaves. In this case, what you need is
+a {@link android.media.MediaPlayer MediaPlayer} controlled by a {@link android.app.Service}, as
+discussed in <a href="mpandservices">Using a Service with MediaPlayer</a>.</p>
+
+<h2 id="mpandservices">Using a Service with MediaPlayer</h2>
+
+<p>If you want your media to play in the background even when your application
+is not onscreen—that is, you want it to continue playing while the user is
+interacting with other applications—then you must start a
+{@link android.app.Service Service} and control the
+{@link android.media.MediaPlayer MediaPlayer} instance from there.
+You should be careful about this setup, because the user and the system have expectations
+about how an application running a background service should interact with the rest of the
+system. If your application does not fulfil those expectations, the user may
+have a bad experience. This section describes the main issues that you should be
+aware of and offers suggestions about how to approach them.</p>
+
+
+<h3 id="asyncprepare">Running asynchronously</h3>
+
+<p>First of all, like an {@link android.app.Activity Activity}, all work in a
+{@link android.app.Service Service} is done in a single thread by
+default—in fact, if you're running an activity and a service from the same application, they
+use the same thread (the "main thread") by default. Therefore, services need to
+process incoming intents quickly
+and never perform lengthy computations when responding to them. If any heavy
+work or blocking calls are expected, you must do those tasks asynchronously: either from
+another thread you implement yourself, or using the framework's many facilities
+for asynchronous processing.</p>
+
+<p>For instance, when using a {@link android.media.MediaPlayer} from your main thread,
+you should call {@link android.media.MediaPlayer#prepareAsync prepareAsync()} rather than
+{@link android.media.MediaPlayer#prepare prepare()}, and implement
+a {@link android.media.MediaPlayer.OnPreparedListener MediaPlayer.OnPreparedListener}
+in order to be notified when the preparation is complete and you can start playing.
+For example:</p>
<pre>
-JetPlayer myJet = JetPlayer.getJetPlayer();
-myJet.loadJetFile("/sdcard/level1.jet");
+public class MyService extends Service implements MediaPlayer.OnPreparedListener {
+ private static final ACTION_PLAY = "com.example.action.PLAY";
+ MediaPlayer mMediaPlayer = null;
+
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ ...
+ if (intent.getAction().equals(ACTION_PLAY)) {
+ mMediaPlayer = ... // initialize it here
+ mMediaPlayer.setOnPreparedListener(this);
+ mMediaPlayer.prepareAsync(); // prepare async to not block main thread
+ }
+ }
+
+ /** Called when MediaPlayer is ready */
+ public void onPrepared(MediaPlayer player) {
+ player.start();
+ }
+}
+</pre>
+
+
+<h3 id="asyncerror">Handling asynchronous errors</h3>
+
+<p>On synchronous operations, errors would normally
+be signaled with an exception or an error code, but whenever you use asynchronous
+resources, you should make sure your application is notified
+of errors appropriately. In the case of a {@link android.media.MediaPlayer MediaPlayer},
+you can accomplish this by implementing a
+{@link android.media.MediaPlayer.OnErrorListener MediaPlayer.OnErrorListener} and
+setting it in your {@link android.media.MediaPlayer} instance:</p>
+
+<pre>
+public class MyService extends Service implements MediaPlayer.OnErrorListener {
+ MediaPlayer mMediaPlayer;
+
+ public void initMediaPlayer() {
+ // ...initialize the MediaPlayer here...
+
+ mMediaPlayer.setOnErrorListener(this);
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ // ... react appropriately ...
+ // The MediaPlayer has moved to the Error state, must be reset!
+ }
+}
+</pre>
+
+<p>It's important to remember that when an error occurs, the {@link android.media.MediaPlayer}
+moves to the <em>Error</em> state (see the documentation for the
+{@link android.media.MediaPlayer MediaPlayer} class for the full state diagram)
+and you must reset it before you can use it again.
+
+
+<h3 id="wakelocks">Using wake locks</h3>
+
+<p>When designing applications that play media
+in the background, the device may go to sleep
+while your service is running. Because the Android system tries to conserve
+battery while the device is sleeping, the system tries to shut off any
+of the phone's features that are
+not necessary, including the CPU and the WiFi hardware.
+However, if your service is playing or streaming music, you want to prevent
+the system from interfering with your playback.</p>
+
+<p>In order to ensure that your service continues to run under
+those conditions, you have to use "wake locks." A wake lock is a way to signal to
+the system that your application is using some feature that should
+stay available even if the phone is idle.</p>
+
+<p class="caution"><strong>Notice:</strong> You should always use wake locks sparingly and hold them
+only for as long as truly necessary, because they significantly reduce the battery life of the
+device.</p>
+
+<p>To ensure that the CPU continues running while your {@link android.media.MediaPlayer} is
+playing, call the {@link android.media.MediaPlayer#setWakeMode
+setWakeMode()} method when initializing your {@link android.media.MediaPlayer}. Once you do,
+the {@link android.media.MediaPlayer} holds the specified lock while playing and releases the lock
+when paused or stopped:</p>
+
+<pre>
+mMediaPlayer = new MediaPlayer();
+// ... other initialization here ...
+mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
+</pre>
+
+<p>However, the wake lock acquired in this example guarantees only that the CPU remains awake. If
+you are streaming media over the
+network and you are using Wi-Fi, you probably want to hold a
+{@link android.net.wifi.WifiManager.WifiLock WifiLock} as
+well, which you must acquire and release manually. So, when you start preparing the
+{@link android.media.MediaPlayer} with the remote URL, you should create and acquire the Wi-Fi lock.
+For example:</p>
+
+<pre>
+WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
+ .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
+
+wifiLock.acquire();
+</pre>
+
+<p>When you pause or stop your media, or when you no longer need the
+network, you should release the lock:</p>
+
+<pre>
+wifiLock.release();
+</pre>
+
+
+<h3 id="foregroundserv">Running as a foreground service</h3>
+
+<p>Services are often used for performing background tasks, such as fetching emails,
+synchronizing data, downloading content, amongst other possibilities. In these
+cases, the user is not actively aware of the service's execution, and probably
+wouldn't even notice if some of these services were interrupted and later restarted.</p>
+
+<p>But consider the case of a service that is playing music. Clearly this is a service that the user
+is actively aware of and the experience would be severely affected by any interruptions.
+Additionally, it's a service that the user will likely wish to interact with during its execution.
+In this case, the service should run as a "foreground service." A
+foreground service holds a higher level of importance within the system—the system will
+almost never kill the service, because it is of immediate importance to the user. When running
+in the foreground, the service also must provide a status bar notification to ensure that users are
+aware of the running service and allow them to open an activity that can interact with the
+service.</p>
+
+<p>In order to turn your service into a foreground service, you must create a
+{@link android.app.Notification Notification} for the status bar and call
+{@link android.app.Service#startForeground startForeground()} from the {@link
+android.app.Service}. For example:</p>
+
+<pre>String songName;
+// assign the song name to songName
+PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
+ new Intent(getApplicationContext(), MainActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+Notification notification = new Notification();
+notification.tickerText = text;
+notification.icon = R.drawable.play0;
+notification.flags |= Notification.FLAG_ONGOING_EVENT;
+notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
+ "Playing: " + songName, pi);
+startForeground(NOTIFICATION_ID, notification);
+</pre>
+
+<p>While your service is running in the foreground, the notification you
+configured is visible in the notification area of the device. If the user
+selects the notification, the system invokes the {@link android.app.PendingIntent} you supplied. In
+the example above, it opens an activity ({@code MainActivity}).</p>
+
+<p>Figure 1 shows how your notification appears to the user:</p>
+
+<img src='images/notification1.png' />
+
+<img src='images/notification2.png' />
+<p class="img-caption"><strong>Figure 1.</strong> Screenshots of a foreground service's notification, showing the notification icon in the status bar (left) and the expanded view (right).</p>
+
+<p>You should only hold on to the "foreground service" status while your
+service is actually performing something the user is actively aware of. Once
+that is no longer true, you should release it by calling
+{@link android.app.Service#stopForeground stopForeground()}:</p>
+
+<pre>
+stopForeground(true);
+</pre>
+
+<p>For more information, see the documentation about <a
+href="{@docRoot}guide/topics/fundamentals/services.html#Foreground">Services</a> and
+<a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
+
+
+<h3 id="audiofocus">Handling audio focus</h3>
+
+<p>Even though only one activity can run at any given time, Android is a
+multi-tasking environment. This poses a particular challenge to applications
+that use audio, because there is only one audio output and there may be several
+media services competing for its use. Before Android 2.2, there was no built-in
+mechanism to address this issue, which could in some cases lead to a bad user
+experience. For example, when a user is listening to
+music and another application needs to notify the user of something very important,
+the user might not hear the notification tone due to the loud music. Starting with
+Android 2.2, the platform offers a way for applications to negotiate their
+use of the device's audio output. This mechanism is called Audio Focus.</p>
+
+<p>When your application needs to output audio such as music or a notification,
+you should always request audio focus. Once it has focus, it can use the sound output freely, but it should
+always listen for focus changes. If it is notified that it has lost the audio
+focus, it should immediately either kill the audio or lower it to a quiet level
+(known as "ducking"—there is a flag that indicates which one is appropriate) and only resume
+loud playback after it receives focus again.</p>
+
+<p>Audio Focus is cooperative in nature. That is, applications are expected
+(and highly encouraged) to comply with the audio focus guidelines, but the
+rules are not enforced by the system. If an application wants to play loud
+music even after losing audio focus, nothing in the system will prevent that.
+However, the user is more likely to have a bad experience and will be more
+likely to uninstall the misbehaving application.</p>
+
+<p>To request audio focus, you must call
+{@link android.media.AudioManager#requestAudioFocus requestAudioFocus()} from the {@link
+android.media.AudioManager}, as the example below demonstrates:</p>
+
+<pre>
+AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN);
+
+if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
+ // could not get audio focus.
+}
+</pre>
+
+<p>The first parameter to {@link android.media.AudioManager#requestAudioFocus requestAudioFocus()}
+is an {@link android.media.AudioManager.OnAudioFocusChangeListener
+AudioManager.OnAudioFocusChangeListener},
+whose {@link android.media.AudioManager.OnAudioFocusChangeListener#onAudioFocusChange
+onAudioFocusChange()} method is called whenever there is a change in audio focus. Therefore, you
+should also implement this interface on your service and activities. For example:</p>
+
+<pre>
+class MyService extends Service
+ implements AudioManager.OnAudioFocusChangeListener {
+ // ....
+ public void onAudioFocusChange(int focusChange) {
+ // Do something based on focus change...
+ }
+}
+</pre>
+
+<p>The <code>focusChange</code> parameter tells you how the audio focus has changed, and
+can be one of the following values (they are all constants defined in
+{@link android.media.AudioManager AudioManager}):</p>
+
+<ul>
+<li>{@link android.media.AudioManager#AUDIOFOCUS_GAIN}: You have gained the audio focus.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS}: You have lost the audio focus for a
+presumably long time.
+You must stop all audio playback. Because you should expect not to have focus back
+for a long time, this would be a good place to clean up your resources as much
+as possible. For example, you should release the {@link android.media.MediaPlayer}.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}: You have
+temporarily lost audio focus, but should receive it back shortly. You must stop
+all audio playback, but you can keep your resources because you will probably get
+focus back shortly.</li>
+
+<li>{@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}: You have temporarily
+lost audio focus,
+but you are allowed to continue to play audio quietly (at a low volume) instead
+of killing audio completely.</li>
+</ul>
+
+<p>Here is an example implementation:</p>
+
+<pre>
+public void onAudioFocusChange(int focusChange) {
+ switch (focusChange) {
+ case AudioManager.AUDIOFOCUS_GAIN:
+ // resume playback
+ if (mMediaPlayer == null) initMediaPlayer();
+ else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
+ mMediaPlayer.setVolume(1.0f, 1.0f);
+ break;
+
+ case AudioManager.AUDIOFOCUS_LOSS:
+ // Lost focus for an unbounded amount of time: stop playback and release media player
+ if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ break;
+
+ case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+ // Lost focus for a short time, but we have to stop
+ // playback. We don't release the media player because playback
+ // is likely to resume
+ if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
+ break;
+
+ case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+ // Lost focus for a short time, but it's ok to keep playing
+ // at an attenuated level
+ if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
+ break;
+ }
+}
+</pre>
+
+<p>Keep in mind that the audio focus APIs are available only with API level 8 (Android 2.2)
+and above, so if you want to support previous
+versions of Android, you should adopt a backward compatibility strategy that
+allows you to use this feature if available, and fall back seamlessly if not.</p>
+
+<p>You can achieve backward compatibility either by calling the audio focus methods by reflection
+or by implementing all the audio focus features in a separate class (say,
+<code>AudioFocusHelper</code>). Here is an example of such a class:</p>
+
+<pre>
+public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener {
+ AudioManager mAudioManager;
+
+ // other fields here, you'll probably hold a reference to an interface
+ // that you can use to communicate the focus changes to your Service
+
+ public AudioFocusHelper(Context ctx, /* other arguments here */) {
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ // ...
+ }
+
+ public boolean requestFocus() {
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
+ mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN);
+ }
+
+ public boolean abandonFocus() {
+ return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
+ mAudioManager.abandonAudioFocus(this);
+ }
+
+ @Override
+ public void onAudioFocusChange(int focusChange) {
+ // let your service know about the focus change
+ }
+}
+</pre>
+
+
+<p>You can create an instance of <code>AudioFocusHelper</code> class only if you detect that
+the system is running API level 8 or above. For example:</p>
+
+<pre>
+if (android.os.Build.VERSION.SDK_INT >= 8) {
+ mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
+} else {
+ mAudioFocusHelper = null;
+}
+</pre>
+
+
+<h3 id="cleanup">Performing cleanup</h3>
+
+<p>As mentioned earlier, a {@link android.media.MediaPlayer} object can consume a significant
+amount of system resources, so you should keep it only for as long as you need and call
+{@link android.media.MediaPlayer#release release()} when you are done with it. It's important
+to call this cleanup method explicitly rather than rely on system garbage collection because
+it might take some time before the garbage collector reclaims the {@link android.media.MediaPlayer},
+as it's only sensitive to memory needs and not to shortage of other media-related resources.
+So, in the case when you're using a service, you should always override the
+{@link android.app.Service#onDestroy onDestroy()} method to make sure you are releasing
+the {@link android.media.MediaPlayer}:</p>
+
+<pre>
+public class MyService extends Service {
+ MediaPlayer mMediaPlayer;
+ // ...
+
+ @Override
+ public void onDestroy() {
+ if (mMediaPlayer != null) mMediaPlayer.release();
+ }
+}
+</pre>
+
+<p>You should always look for other opportunities to release your {@link android.media.MediaPlayer}
+as well, apart from releasing it when being shut down. For example, if you expect not
+to be able to play media for an extended period of time (after losing audio focus, for example),
+you should definitely release your existing {@link android.media.MediaPlayer} and create it again
+later. On the
+other hand, if you only expect to stop playback for a very short time, you should probably
+hold on to your {@link android.media.MediaPlayer} to avoid the overhead of creating and preparing it
+again.</p>
+
+
+
+<h2 id="noisyintent">Handling the AUDIO_BECOMING_NOISY Intent</h2>
+
+<p>Many well-written applications that play audio automatically stop playback when an event
+occurs that causes the audio to become noisy (ouput through external speakers). For instance,
+this might happen when a user is listening to music through headphones and accidentally
+disconnects the headphones from the device. However, this behavior does not happen automatically.
+If you don't implement this feature, audio plays out of the device's external speakers, which
+might not be what the user wants.</p>
+
+<p>You can ensure your app stops playing music in these situations by handling
+the {@link android.media.AudioManager#ACTION_AUDIO_BECOMING_NOISY} intent, for which you can register a receiver by
+adding the following to your manifest:</p>
+
+<pre>
+<receiver android:name=".MusicIntentReceiver">
+ <intent-filter>
+ <action android:name="android.media.AUDIO_BECOMING_NOISY" />
+ </intent-filter>
+</receiver>
+</pre>
+
+<p>This registers the <code>MusicIntentReceiver</code> class as a broadcast receiver for that
+intent. You should then implement this class:</p>
+
+<pre>
+public class MusicIntentReceiver implements android.content.BroadcastReceiver {
+ @Override
+ public void onReceive(Context ctx, Intent intent) {
+ if (intent.getAction().equals(
+ android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
+ // signal your service to stop playback
+ // (via an Intent, for instance)
+ }
+ }
+}
+</pre>
+
+
+
+
+<h2 id="viacontentresolver">Retrieving Media from a Content Resolver</h2>
+
+<p>Another feature that may be useful in a media player application is the ability to
+retrieve music that the user has on the device. You can do that by querying the {@link
+android.content.ContentResolver} for external media:</p>
+
+<pre>
+ContentResolver contentResolver = getContentResolver();
+Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+Cursor cursor = contentResolver.query(uri, null, null, null, null);
+if (cursor == null) {
+ // query failed, handle error.
+} else if (!cursor.moveToFirst()) {
+ // no media on the device
+} else {
+ int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
+ int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
+ do {
+ long thisId = cursor.getLong(idColumn);
+ String thisTitle = cursor.getString(titleColumn);
+ // ...process entry...
+ } while (cursor.moveToNext());
+}
+</pre>
+
+<p>To use this with the {@link android.media.MediaPlayer}, you can do this:</p>
+
+<pre>
+long id = /* retrieve it from somewhere */;
+Uri contentUri = ContentUris.withAppendedId(
+ android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
+
+mMediaPlayer = new MediaPlayer();
+mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+mMediaPlayer.setDataSource(getApplicationContext(), contentUri);
+
+// ...prepare and start...
+</pre>
+
+
+
+<h2 id="jetcontent">Playing JET content</h2>
+
+<p>The Android platform includes a JET engine that lets you add interactive playback of JET audio
+content in your applications. You can create JET content for interactive playback using the
+JetCreator authoring application that ships with the SDK. To play and manage JET content from your
+application, use the {@link android.media.JetPlayer JetPlayer} class.</p>
+
+<p>For a description of JET concepts and instructions on how to use the JetCreator authoring tool,
+see the <a href="{@docRoot}guide/topics/media/jet/jetcreator_manual.html">JetCreator User
+Manual</a>. The tool is available on Windows, OS X, and Linux platforms (Linux does not
+support auditioning of imported assets like with the Windows and OS X versions).
+</p>
+
+<p>Here's an example of how to set up JET playback from a <code>.jet</code> file stored on the SD card:</p>
+
+<pre>
+JetPlayer jetPlayer = JetPlayer.getJetPlayer();
+jetPlayer.loadJetFile("/sdcard/level1.jet");
byte segmentId = 0;
// queue segment 5, repeat once, use General MIDI, transpose by -1 octave
-myJet.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
+jetPlayer.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
// queue segment 2
-myJet.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
+jetPlayer.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
-myJet.play();
+jetPlayer.play();
</pre>
-<p>The SDK includes an example application — JetBoy — that shows how to use {@link android.media.JetPlayer JetPlayer} to create an interactive music soundtrack in your game. It also illustrates how to use JET events to synchronize music and game logic. The application is located at <code><sdk>/platforms/android-1.5/samples/JetBoy</code>.
+<p>The SDK includes an example application — JetBoy — that shows how to use {@link
+android.media.JetPlayer JetPlayer} to create an interactive music soundtrack in your game. It also
+illustrates how to use JET events to synchronize music and game logic. The application is located at
+<code><sdk>/platforms/android-1.5/samples/JetBoy</code>.</p>
-<h2 id="capture">Audio Capture</h2>
-<p>Audio capture from the device is a bit more complicated than audio/video playback, but still fairly simple:</p>
+
+<h2 id="audiocapture">Performing Audio Capture</h2>
+
+<p>Audio capture from the device is a bit more complicated than audio and video playback, but still fairly simple:</p>
<ol>
- <li>Create a new instance of {@link android.media.MediaRecorder android.media.MediaRecorder} using <code>new</code></li>
+ <li>Create a new instance of {@link android.media.MediaRecorder android.media.MediaRecorder}.</li>
<li>Set the audio source using
{@link android.media.MediaRecorder#setAudioSource MediaRecorder.setAudioSource()}. You will probably want to use
- <code>MediaRecorder.AudioSource.MIC</code></li>
+ <code>MediaRecorder.AudioSource.MIC</code>.</li>
<li>Set output file format using
- {@link android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}
+ {@link android.media.MediaRecorder#setOutputFormat MediaRecorder.setOutputFormat()}.
</li>
<li>Set output file name using
- {@link android.media.MediaRecorder#setOutputFile MediaRecorder.setOutputFile()}
+ {@link android.media.MediaRecorder#setOutputFile MediaRecorder.setOutputFile()}.
</li>
- <li>Set the audio encoder using
- {@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}
+ <li>Set the audio encoder using
+ {@link android.media.MediaRecorder#setAudioEncoder MediaRecorder.setAudioEncoder()}.
</li>
<li>Call {@link android.media.MediaRecorder#prepare MediaRecorder.prepare()}
on the MediaRecorder instance.</li>
- <li>To start audio capture, call
+ <li>To start audio capture, call
{@link android.media.MediaRecorder#start MediaRecorder.start()}. </li>
<li>To stop audio capture, call {@link android.media.MediaRecorder#stop MediaRecorder.stop()}.
<li>When you are done with the MediaRecorder instance, call
@@ -354,3 +968,4 @@
</pre>
+
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index a996ccc..ea778c1 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -335,80 +335,101 @@
</tr>
<tr id="SmallestScreenWidthQualifier">
<td>Smallest screen width</td>
- <td>Examples:<br/>
+ <td><code>sw<N>dp</code><br/><br/>
+ Examples:<br/>
<code>sw320dp</code><br/>
<code>sw600dp</code><br/>
<code>sw720dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum "smallest screen width," in "dp" units, at which the resource
- should be used. This configuration value represents the base screen size
- of the device, regardless of the orientation of the display. It is based
- on the smallest width the application will have in which to perform its
- UI layout (in dp units) regardless of the orientation of the screen. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space.</p>
- <p>Some values you may use here for common screen sizes:</p>
+ <p>Specifies the "smallest width" in {@code dp} units that must be available to your
+ application in order for the resources to be used, regardless of the screen's current
+ orientation. For example, if your layout requires that its shortest side be at least 600
+ dp in length at all times, then you can use this to create the layout resources, {@code
+ res/layout-sw600dp/}, and the system will use them only when the shortest side of
+ available screen space it at least 600dp.</p>
+ <p>The width against which the system compares your value takes into account screen
+ decorations and system UI. For example, if the device has some persistent UI elements on the
+ left or right edge of the display, the system declares its own available width as one that
+ is smaller than the actual screen size, accounting for these UI elements because those are
+ screen pixels not available for your UI. Thus, the value you use should be the actual
+ smallest width required by your layout.</p>
+ <p>Some values you might use here for common screen sizes:</p>
<ul>
- <li>240x320 ldpi (QVGA phone): 320
- <li>320x480 mdpi (phone): 320
- <li>480x800 hdpi (high density phone): 320
- <li>480x800 mdpi (tablet/phone): 480
- <li>600x1024 mdpi (7" tablet): 600
- <li>720x1280 mdpi (10" tablet): 720
+ <li>320, for devices with screen configurations such as:
+ <ul>
+ <li>240x320 ldpi (QVGA handset)</li>
+ <li>320x480 mdpi (handset)</li>
+ <li>480x800 hdpi (high density handset)</li>
+ </ul>
+ </li>
+ <li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
+ <li>600, for screens such as 600x1024 mdpi (7" tablet).</li>
+ <li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
</ul>
- <p><em>Added in API Level 13.</em></p>
- <p>Also see the {@link android.content.res.Configuration#smallestScreenWidthDp}
- configuration field, which holds the current smallest screen width.</p>
+ <p>When your application provides multiple resource directories with different values for
+ this qualifier, the system uses the one closest to (without exceeding) the smallest width
+ for the available space. </p>
+ <p><em>Added in API level 13.</em></p>
+ <p>Also see the <a
+ href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+ android:requiresSmallestWidthDp}</a> attribute, which declares the smallest available width
+ with which your application is compatible, and the {@link
+ android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds
+ the current smallest screen width for the device.</p>
</td>
</tr>
<tr id="ScreenWidthQualifier">
<td>Screen width</td>
- <td>Examples:<br/>
+ <td><code>w<N>dp</code><br/><br/>
+ Examples:<br/>
<code>w720dp</code><br/>
<code>w1024dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum screen width, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual width.
- When multiple screen width configurations are available, the closest to
- the current screen width will be used. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space.</p>
- <p><em>Added in API Level 13.</em></p>
+ <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+ should be used—defined by the <code><N></code> value. This
+ configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual width.</p>
+ <p>When your application provides multiple resource directories with different values
+ for this configuration, the system uses the one closest to (without exceeding)
+ the device's current screen width. The
+ value here takes into account screen decorations, so if the device has some
+ persistent UI elements on the left or right edge of the display, it
+ uses a value for the width that is smaller than the real screen size, accounting
+ for these UI elements and reducing the application's available space.</p>
+ <p><em>Added in API level 13.</em></p>
<p>Also see the {@link android.content.res.Configuration#screenWidthDp}
configuration field, which holds the current screen width.</p>
</td>
</tr>
<tr id="ScreenHeightQualifier">
<td>Screen height</td>
- <td>Examples:<br/>
+ <td><code>h<N>dp</code><br/><br/>
+ Examples:<br/>
<code>h720dp</code><br/>
<code>h1024dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum screen height, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual height.
- When multiple screen height configurations are available, the closest to
- the current screen height will be used. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space. Screen
+ <p>Specifies a minimum screen height, in "dp" units at which the resource
+ should be used—defined by the <code><N></code> value. This
+ configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual height.</p>
+ <p>When your application provides multiple resource directories with different values
+ for this configuration, the system uses the one closest to (without exceeding)
+ the device's current screen height. The
+ value here takes into account screen decorations, so if the device has some
+ persistent UI elements on the top or bottom edge of the display, it uses
+ a value for the height that is smaller than the real screen size, accounting
+ for these UI elements and reducing the application's available space. Screen
decorations that are not fixed (such as a phone status bar that can be
hidden when full screen) are <em>not</em> accounted for here, nor are
- window decorations like title bar, so applications must be prepared to
+ window decorations like the title bar or action bar, so applications must be prepared to
deal with a somewhat smaller space than they specify.
- <p><em>Added in API Level 13.</em></p>
+ <p><em>Added in API level 13.</em></p>
<p>Also see the {@link android.content.res.Configuration#screenHeightDp}
configuration field, which holds the current screen width.</p>
</td>
@@ -444,9 +465,9 @@
medium-density HVGA screen. The minimum layout size for this screen configuration
is approximately 720x960 dp units. In most cases, devices with extra large
screens would be too large to carry in a pocket and would most likely
- be tablet-style devices. <em>Added in API Level 9.</em></li>
+ be tablet-style devices. <em>Added in API level 9.</em></li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a> for more information.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -465,7 +486,7 @@
<li>{@code long}: Long screens, such as WQVGA, WVGA, FWVGA</li>
<li>{@code notlong}: Not long screens, such as QVGA, HVGA, and VGA</li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>This is based purely on the aspect ratio of the screen (a "long" screen is wider). This
is not related to the screen orientation.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -503,7 +524,7 @@
<li>{@code car}: Device is in a car dock</li>
<li>{@code desk}: Device is in a desk dock</li>
</ul>
- <p><em>Added in API Level 8.</em></p>
+ <p><em>Added in API level 8.</em></p>
<p>This can change during the life of your application if the user places the device in a
dock. You can enable or disable this mode using {@link
android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
@@ -521,7 +542,7 @@
<li>{@code night}: Night time</li>
<li>{@code notnight}: Day time</li>
</ul>
- <p><em>Added in API Level 8.</em></p>
+ <p><em>Added in API level 8.</em></p>
<p>This can change during the life of your application if night mode is left in
auto mode (default), in which case the mode changes based on the time of day. You can enable
or disable this mode using {@link android.app.UiModeManager}. See <a
@@ -549,7 +570,7 @@
<li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
to match the device density.</li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>There is thus a 3:4:6:8 scaling ratio between the four densities, so a 9x9 bitmap
in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
<p>When Android selects which resource files to use,
@@ -689,17 +710,17 @@
</tr>
-->
<tr id="VersionQualifier">
- <td>Platform Version (API Level)</td>
+ <td>Platform Version (API level)</td>
<td>Examples:<br/>
<code>v3</code><br/>
<code>v4</code><br/>
<code>v7</code><br/>
etc.</td>
<td>
- <p>The API Level supported by the device. For example, <code>v1</code> for API Level
-1 (devices with Android 1.0 or higher) and <code>v4</code> for API Level 4 (devices with Android
+ <p>The API level supported by the device. For example, <code>v1</code> for API level
+1 (devices with Android 1.0 or higher) and <code>v4</code> for API level 4 (devices with Android
1.6 or higher). See the <a
-href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> document for more information
+href="{@docRoot}guide/appendix/api-levels.html">Android API levels</a> document for more information
about these values.</p>
<p class="caution"><strong>Caution:</strong> Android 1.5 and 1.6 only match resources
with this qualifier when it exactly matches the platform version. See the section below about <a
@@ -863,7 +884,7 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
minSdkVersion}</a> is set to 4, and you qualify all of your drawable resources using <a
href="#NightQualifier">night mode</a> ({@code night} or {@code notnight}, which were added in API
-Level 8), then an API Level 4 device cannot access your drawable resources and will crash. In this
+Level 8), then an API level 4 device cannot access your drawable resources and will crash. In this
case, you probably want {@code notnight} to be your default resources, so you should exclude that
qualifier so your drawable resources are in either {@code drawable/} or {@code drawable-night/}.</p>
@@ -896,7 +917,7 @@
<dd>{@code long} and {@code notlong}</dd>
</dl>
-<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API Level 3) and
+<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API level 3) and
lower does not support them. If you use these configuration qualifiers and do not provide
corresponding default resources, then an Android 1.5 device might use any one of the resource
directories named with the above screen configuration qualifiers, because it ignores these
@@ -926,9 +947,9 @@
<p>You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that
automatically applies an appropriate <a href="#VersionQualifier">version qualifier</a> to any
resource directory named with a qualifier that does not exist in Android 1.0. For example, because
-the density qualifier was introduced in Android 1.6 (API Level 4), when the packaging tool
+the density qualifier was introduced in Android 1.6 (API level 4), when the packaging tool
encounters a resource directory using the density qualifier, it adds {@code v4} to the directory
-name to ensure that older versions do not use those resources (only API Level 4 and higher support
+name to ensure that older versions do not use those resources (only API level 4 and higher support
that qualifier). Thus, by putting your medium-density resources in a directory <em>without</em> the
{@code mdpi} qualifier, they are still accessible by Android 1.5, and any device that supports the
density qualifer and has a medium-density screen also uses the default resources (which are mdpi)
@@ -937,7 +958,7 @@
</li>
</ol>
-<p class="note"><strong>Note:</strong> Later versions of Android, such as API Level 8,
+<p class="note"><strong>Note:</strong> Later versions of Android, such as API level 8,
introduce other configuration qualifiers that older version do not support. To provide the best
compatibility, you should always include a set of default resources for each type of resource
that your application uses, as discussed above to provide the best device compatibility.</p>
@@ -1068,7 +1089,7 @@
<p>The correct behavior is for the system to match resources marked with a <a
href="#VersionQualifier">version qualifier</a> equal
-to or less than the platform version on the device, but on Android 1.5 and 1.6, (API Level 3 and 4),
+to or less than the platform version on the device, but on Android 1.5 and 1.6, (API level 3 and 4),
there is a bug that causes the system to match resources marked with the version qualifier
only when it exactly matches the version on the device.</p>
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
index 7ac5ff1..218511b 100644
--- a/docs/html/guide/topics/search/index.jd
+++ b/docs/html/guide/topics/search/index.jd
@@ -52,7 +52,13 @@
<p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
search your data. To perform a search, you need to use APIs appropriate for your data. For example,
if your data is stored in an SQLite database, you should use the {@link android.database.sqlite}
-APIs to perform searches.</p>
+APIs to perform searches.
+<br/><br/>
+Also, there is no guarantee that every device provides a dedicated SEARCH button to invoke the
+search interface in your application. When using the search dialog or a custom interface, you
+must always provide a search button in your UI that activates the search interface. For more
+information, see <a href="search-dialog.html#InvokingTheSearchDialog">Invoking the search
+dialog</a>.</p>
<p>The following documents show you how to use Android's framework to implement search:</p>
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index af6c8f2..d869a44 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -17,29 +17,30 @@
<h2>In this document</h2>
<ol>
-<li><a href="#TheBasics">The Basics</a></li>
-<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
-<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
- <ol>
- <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
- <li><a href="#EnableSearch">Enabling the search dialog and search widget</a></li>
- <li><a href="#PerformingSearch">Performing a search</a></li>
- </ol>
-</li>
-<li><a href="#UsingTheSearchDialog">Using the Search Dialog</a>
- <ol>
- <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
- <li><a href="#SearchContextData">Passing search context data</a></li>
- </ol>
-</li>
-<li><a href="#UsingSearchWidget">Using the Search Widget</a>
- <ol>
- <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
- <li><a href="#WidgetFeatures">Other search widget features</a></li>
- </ol>
-</li>
-<li><a href="#VoiceSearch">Adding Voice Search</a></li>
-<li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
+ <li><a href="#TheBasics">The Basics</a></li>
+ <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
+ <li><a href="#SearchableActivity">Creating a Searchable Activity</a>
+ <ol>
+ <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
+ <li><a href="#PerformingSearch">Performing a search</a></li>
+ </ol>
+ </li>
+ <li><a href="#SearchDialog">Using the Search Dialog</a>
+ <ol>
+ <li><a href="#InvokingTheSearchDialog">Invoking the search dialog</a></li>
+ <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
+ <li><a href="#SearchContextData">Passing search context data</a></li>
+ </ol>
+ </li>
+ <li><a href="#UsingSearchWidget">Using the Search Widget</a>
+ <ol>
+ <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
+ <li><a href="#WidgetFeatures">Other search widget features</a></li>
+ <li><a href="#UsingBoth">Using both the widget and the dialog</a></li>
+ </ol>
+ </li>
+ <li><a href="#VoiceSearch">Adding Voice Search</a></li>
+ <li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
</ol>
<h2>Key classes</h2>
@@ -494,13 +495,13 @@
<h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3>
-<p>As mentioned above, the device SEARCH button and {@link android.app.Activity#onSearchRequested
-onSearchRequested()} method will open the search dialog, as long as the current activity
-has declared the searchable activity to use, as shown in the previous section.</p>
+<p>As mentioned above, the device SEARCH button will open the search dialog as long as the current
+activity has declared in the manifest the searchable activity to use.</p>
-<p>However, you should not assume that a SEARCH button is available on the user's device. You
-should always provide another search button in your UI that activates the search dialog by calling
-{@link android.app.Activity#onSearchRequested()}.</p>
+<p>However, some devices do not include a dedicated SEARCH button, so you should not assume that
+it's always available. When using the search dialog, you must <strong>always provide another search
+button in your UI</strong> that activates the search dialog by calling {@link
+android.app.Activity#onSearchRequested()}.</p>
<p>For instance, you should either provide a menu item in your <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your
@@ -510,12 +511,6 @@
medium and high density screens, which you can use for your search menu item or button (low-density
screens scale-down the hdpi image by one half). </p>
-<!-- ... maybe this should go into the Creating Menus document ....
-<p>If you chose to provide a shortcut key for the menu item, using {@link
-android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
-key character, representing the default search key.</p>
--->
-
<p>You can also enable "type-to-search" functionality, which activates the search dialog when the
user starts typing on the keyboard—the keystrokes are inserted into the search dialog. You can
enable type-to-search in your activity by calling
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index e4e1215..2e172f5 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -54,6 +54,10 @@
</li>
</ol>
+ <h2>Download</h2>
+ <ol>
+ <li><a href="https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package</a></li>
+ </ol>
<h2>See also</h2>
@@ -66,6 +70,12 @@
<h2>Where to buy</h2>
<ol>
+ <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">
+ Modern Device</a></li>
+
+ <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
+ Seeed Studio</a></li>
+
<li><a href=
"http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
RT Corp</a></li>
@@ -77,8 +87,6 @@
<li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
DIY Drones</a></li>
- <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">
- Modern Device</a></li>
</ol>
</div>
</div>
@@ -106,15 +114,22 @@
development boards:</p>
<ul>
+ <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern
+ Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
+ <li><a href="http://www.seeedstudio.com/depot/seeeduino-adk-main-board-p-846.html">
+ Seeed Studio</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
<li><a href="http://www.rt-net.jp/shop/index.php?main_page=product_info&cPath=3_4&products_id=1">
RT Corp</a> provides an Arduino-compatible board based on the Android ADK board design.</li>
+
<li><a href="http://www.microchip.com/android">Microchip</a> provides a A PIC based USB
microcontroller board.</li>
+
<li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">DIY
Drones</a> provides an Arduino-compatible board geared towards RC (radio controlled) and UAV
(unmanned aerial vehicle) enthusiasts.</li>
- <li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">Modern
- Device</a> provides an Arduino-compatible board that supports the ADK firmware.</li>
+
</ul>
<p>We expect more hardware distributers to create a variety of kits, so please stay tuned for
@@ -125,7 +140,7 @@
accessory that is based on the <a href="http://www.arduino.cc/">Arduino open source electronics
prototyping platform</a>, the accessory's hardware design files, code that implements the
accessory's firmware, and the Android application that interacts with the accessory. The hardware
- design files and firmware code are contained in the <a href=
+ design files and firmware code are contained in the <a href=ctive
"https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package download</a>.</p>
<p>The main hardware and software components of the ADK include:</p>
diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/wireless/bluetooth.jd
index 48632ea..0af1d2c 100644
--- a/docs/html/guide/topics/wireless/bluetooth.jd
+++ b/docs/html/guide/topics/wireless/bluetooth.jd
@@ -1,57 +1,61 @@
page.title=Bluetooth
@jd:body
-<div id="qv-wrapper">
-<div id="qv">
-
- <h2>Quickview</h2>
- <ul>
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>Quickview</h2>
+ <ul>
<li>Android's bluetooth APIs allow your application to perform wireless data transactions with
-other devices</li>
- </ul>
-
- <h2>In this document</h2>
- <ol>
- <li><a href="#TheBasics">The Basics</a></li>
- <li><a href="#Permissions">Bluetooth Permissions</a></li>
- <li><a href="#SettingUp">Setting Up Bluetooth</a></li>
- <li><a href="#FindingDevices">Finding Devices</a>
- <ol>
- <li><a href="#QueryingPairedDevices">Querying paired devices</a></li>
- <li><a href="#DiscoveringDevices">Discovering devices</a></li>
- </ol></li>
- <li><a href="#ConnectingDevices">Connecting Devices</a>
- <ol>
- <li><a href="#ConnectingAsAServer">Connecting as a server</a></li>
- <li><a href="#ConnectingAsAClient">Connecting as a client</a></li>
- </ol></li>
+other devices</li>
+ </ul>
+
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#TheBasics">The Basics</a></li>
+ <li><a href="#Permissions">Bluetooth Permissions</a></li>
+ <li><a href="#SettingUp">Setting Up Bluetooth</a></li>
+ <li><a href="#FindingDevices">Finding Devices</a>
+ <ol>
+ <li><a href="#QueryingPairedDevices">Querying paired devices</a></li>
+ <li><a href="#DiscoveringDevices">Discovering devices</a></li>
+ </ol></li>
+ <li><a href="#ConnectingDevices">Connecting Devices</a>
+ <ol>
+ <li><a href="#ConnectingAsAServer">Connecting as a server</a></li>
+ <li><a href="#ConnectingAsAClient">Connecting as a client</a></li>
+ </ol></li>
<li><a href="#ManagingAConnection">Managing a Connection</a></li>
- </ol>
-
- <h2>Key classes</h2>
- <ol>
- <li>{@link android.bluetooth.BluetoothAdapter}</li>
- <li>{@link android.bluetooth.BluetoothDevice}</li>
- <li>{@link android.bluetooth.BluetoothSocket}</li>
- <li>{@link android.bluetooth.BluetoothServerSocket}</li>
- </ol>
-
- <h2>Related samples</h2>
- <ol>
- <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li>
- </ol>
-
-</div>
-</div>
-
-
+ <li><a href="#Profiles">Working with Profiles</a>
+ <ol>
+ <li><a href="#AT-Commands">Vendor-specific AT commands</a>
+ </ol></li>
+ </ol>
+
+ <h2>Key classes</h2>
+ <ol>
+ <li>{@link android.bluetooth.BluetoothAdapter}</li>
+ <li>{@link android.bluetooth.BluetoothDevice}</li>
+ <li>{@link android.bluetooth.BluetoothSocket}</li>
+ <li>{@link android.bluetooth.BluetoothServerSocket}</li>
+ </ol>
+
+ <h2>Related samples</h2>
+ <ol>
+ <li><a href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat</a></li>
+ </ol>
+
+</div>
+</div>
+
+
<p>The Android platform includes support for the Bluetooth network stack,
which allows a device to wirelessly exchange data with other Bluetooth devices.
The application framework provides access to the Bluetooth functionality through
the Android Bluetooth APIs. These APIs let applications wirelessly
connect to other Bluetooth devices, enabling point-to-point and multipoint
-wireless features.</p>
-
+wireless features.</p>
+
<p>Using the Bluetooth APIs, an Android application can perform the
following:</p>
<ul>
@@ -66,17 +70,17 @@
<h2 id="TheBasics">The Basics</h2>
-<p>This document describes how to us the Android Bluetooth APIs to accomplish
+<p>This document describes how to use the Android Bluetooth APIs to accomplish
the four major tasks necessary to communicate using Bluetooth: setting up
Bluetooth, finding devices that are either paired or available in the local
-area, connecting devices, and transferring data between devices.</p>
-
+area, connecting devices, and transferring data between devices.</p>
+
<p>All of the Bluetooth APIs are available in the {@link android.bluetooth}
-package. Here's a summary of the classes you will need to create Bluetooth
-connections:</p>
-
-<dl>
-<dt>{@link android.bluetooth.BluetoothAdapter}</dt>
+package. Here's a summary of the classes and interfaces you will need to create Bluetooth
+connections:</p>
+
+<dl>
+<dt>{@link android.bluetooth.BluetoothAdapter}</dt>
<dd>Represents the local Bluetooth adapter (Bluetooth radio). The
{@link android.bluetooth.BluetoothAdapter} is the entry-point for all Bluetooth
interaction. Using this,
@@ -84,51 +88,72 @@
devices, instantiate a {@link android.bluetooth.BluetoothDevice} using a known
MAC address, and create a {@link android.bluetooth.BluetoothServerSocket} to
listen for communications
-from other devices.</dd>
-
-<dt>{@link android.bluetooth.BluetoothDevice}</dt>
+from other devices.</dd>
+
+<dt>{@link android.bluetooth.BluetoothDevice}</dt>
<dd>Represents a remote Bluetooth device. Use this to request a connection
with a remote device through a {@link android.bluetooth.BluetoothSocket} or
query information about the
-device such as its name, address, class, and bonding state.</dd>
-
-<dt>{@link android.bluetooth.BluetoothSocket}</dt>
+device such as its name, address, class, and bonding state.</dd>
+
+<dt>{@link android.bluetooth.BluetoothSocket}</dt>
<dd>Represents the interface for a Bluetooth socket (similar to a TCP
{@link java.net.Socket}). This is the connection point that allows
an application to exchange data with another Bluetooth device via InputStream
-and OutputStream.</dd>
-
-<dt>{@link android.bluetooth.BluetoothServerSocket}</dt>
+and OutputStream.</dd>
+
+<dt>{@link android.bluetooth.BluetoothServerSocket}</dt>
<dd>Represents an open server socket that listens for incoming requests
(similar to a TCP {@link java.net.ServerSocket}). In order to connect two
Android devices, one device must open a server socket with this class. When a
remote Bluetooth device makes a connection request to the this device, the
{@link android.bluetooth.BluetoothServerSocket} will return a connected {@link
android.bluetooth.BluetoothSocket} when the
-connection is accepted.</dd>
-
-<dt>{@link android.bluetooth.BluetoothClass}</dt>
+connection is accepted.</dd>
+
+<dt>{@link android.bluetooth.BluetoothClass}</dt>
<dd>Describes the general characteristics and capabilities of a Bluetooth
device. This is a read-only set of properties that define the device's major and
minor device classes and its services. However, this does not reliably describe
all Bluetooth profiles and services supported by the device, but is useful as a
-hint to the device type.</dd>
-</dl>
+hint to the device type.</dd>
+
+<dt>{@link android.bluetooth.BluetoothProfile}</dt> <dd>An interface that
+represents a Bluetooth profile. A <em>Bluetooth profile</em> is a wireless
+interface specification for Bluetooth-based communication between devices. An
+example is the Hands-Free profile. For more discussion of profiles, see <a
+href="#Profiles">Working with Profiles</a></dd>
+<dt>{@link android.bluetooth.BluetoothHeadset}</dt> <dd>Provides support for
+Bluetooth headsets to be used with mobile phones. This includes both Bluetooth
+Headset and Hands-Free (v1.5) profiles.</dd>
+<dt>{@link android.bluetooth.BluetoothA2dp}</dt> <dd> Defines how high quality
+audio can be streamed from one device to another over a Bluetooth connection.
+"A2DP" stands for Advanced Audio Distribution Profile.</dd>
+<dt>{@link android.bluetooth.BluetoothProfile.ServiceListener}</dt>
-<h2 id="Permissions">Bluetooth Permissions</h2>
-
+<dd>An interface that notifies {@link android.bluetooth.BluetoothProfile} IPC
+clients when they have been connected to or disconnected from the service (that
+is, the internal service that runs a particular profile). </dd>
+
+</dl>
+
+
+
+
+<h2 id="Permissions">Bluetooth Permissions</h2>
+
<p>In order to use Bluetooth features in your application, you need to declare
at least one of two Bluetooth permissions: {@link
android.Manifest.permission#BLUETOOTH} and {@link
-android.Manifest.permission#BLUETOOTH_ADMIN}.</p>
-
+android.Manifest.permission#BLUETOOTH_ADMIN}.</p>
+
<p>You must request the {@link android.Manifest.permission#BLUETOOTH} permission
in order to perform any Bluetooth communication, such as requesting a
-connection, accepting a connection, and transferring data.</p>
-
+connection, accepting a connection, and transferring data.</p>
+
<p>You must request the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission in order to initiate device discovery or manipulate Bluetooth
settings. Most applications need this permission solely for the
@@ -136,40 +161,40 @@
permission should not be used, unless the application is a "power manager" that
will modify Bluetooth settings upon user request. <strong>Note:</strong> If you
use {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission, then must
-also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p>
-
+also have the {@link android.Manifest.permission#BLUETOOTH} permission.</p>
+
<p>Declare the Bluetooth permission(s) in your application manifest file. For
-example:</p>
-
-<pre>
+example:</p>
+
+<pre>
<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
...
</manifest>
-</pre>
-
+</pre>
+
<p>See the <a
-href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a>
-reference for more information about declaring application permissions.</p>
-
-
-<h2 id="SettingUp">Setting Up Bluetooth</h2>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_enable_request.png" />
+href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a>
+reference for more information about declaring application permissions.</p>
+
+
+<h2 id="SettingUp">Setting Up Bluetooth</h2>
+
+<div class="figure" style="width:200px">
+<img src="{@docRoot}images/bt_enable_request.png" />
<strong>Figure 1:</strong> The enabling Bluetooth dialog.
-</div>
-
+</div>
+
<p>Before your application can communicate over Bluetooth, you need to verify
-that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p>
-
+that Bluetooth is supported on the device, and if so, ensure that it is enabled.</p>
+
<p>If Bluetooth is not supported, then you should gracefully disable any
Bluetooth features. If Bluetooth is supported, but disabled, then you can request that the
user enable Bluetooth without leaving your application. This setup is
-accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p>
-
-
-<ol>
+accomplished in two steps, using the {@link android.bluetooth.BluetoothAdapter}.</p>
+
+
+<ol>
<li>Get the {@link android.bluetooth.BluetoothAdapter}
<p>The {@link android.bluetooth.BluetoothAdapter} is required for any and all Bluetooth
activity. To get the {@link android.bluetooth.BluetoothAdapter}, call the static {@link
@@ -178,15 +203,15 @@
Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for the
entire system, and your application can interact with it using this object. If
{@link android.bluetooth.BluetoothAdapter#getDefaultAdapter()} returns null,
-then the device does not support Bluetooth and your story ends here. For example:</p>
-<pre>
+then the device does not support Bluetooth and your story ends here. For example:</p>
+<pre>
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
-</pre>
-</li>
-
+</pre>
+</li>
+
<li>Enable Bluetooth
<p>Next, you need to ensure that Bluetooth is enabled. Call {@link
android.bluetooth.BluetoothAdapter#isEnabled()} to check whether Bluetooth is
@@ -195,26 +220,26 @@
android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()}
with the {@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_ENABLE} action Intent.
This will issue a request to enable Bluetooth through the system settings (without
-stopping your application). For example:</p>
-<pre>
+stopping your application). For example:</p>
+<pre>
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
-</pre>
-
+</pre>
+
<p>A dialog will appear requesting user permission to enable Bluetooth, as shown
in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth
-and focus will return to your application once the process completes (or fails).</p>
+and focus will return to your application once the process completes (or fails).</p>
<p>If enabling Bluetooth succeeds, your Activity will receive the {@link
android.app.Activity#RESULT_OK} result code in the {@link
android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()}
callback. If Bluetooth was not enabled
due to an error (or the user responded "No") then the result code will be {@link
-android.app.Activity#RESULT_CANCELED}.</p>
-</li>
-</ol>
-
+android.app.Activity#RESULT_CANCELED}.</p>
+</li>
+</ol>
+
<p>Optionally, your application can also listen for the
{@link android.bluetooth.BluetoothAdapter#ACTION_STATE_CHANGED} broadcast Intent, which
the system will broadcast whenever the Bluetooth state has changed. This broadcast contains
@@ -226,21 +251,21 @@
android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}, and {@link
android.bluetooth.BluetoothAdapter#STATE_OFF}. Listening for this
broadcast can be useful to detect changes made to the Bluetooth state while your
-app is running.</p>
-
+app is running.</p>
+
<p class="note"><strong>Tip:</strong> Enabling discoverability will automatically
enable Bluetooth. If you plan to consistently enable device discoverability before
performing Bluetooth activity, you can skip
step 2 above. Read about <a href="#EnablingDiscoverability">enabling discoverability</a>,
-below.</p>
-
-
-<h2 id="FindingDevices">Finding Devices</h2>
-
+below.</p>
+
+
+<h2 id="FindingDevices">Finding Devices</h2>
+
<p>Using the {@link android.bluetooth.BluetoothAdapter}, you can find remote Bluetooth
devices either through device discovery or by querying the list of paired (bonded)
-devices.</p>
-
+devices.</p>
+
<p>Device discovery is a scanning procedure that searches the local area for
Bluetooth enabled devices and then requesting some information about each one
(this is sometimes referred to as "discovering," "inquiring" or "scanning").
@@ -249,15 +274,15 @@
discoverable, it will respond to the discovery request by sharing some
information, such as the device name, class, and its unique MAC address. Using
this information, the device performing discovery can then choose to initiate a
-connection to the discovered device.</p>
-
+connection to the discovered device.</p>
+
<p>Once a connection is made with a remote device for the first time, a pairing
request is automatically presented to the user. When a device is
paired, the basic information about that device (such as the device name, class,
and MAC address) is saved and can be read using the Bluetooth APIs. Using the
known MAC address for a remote device, a connection can be initiated with it at
-any time without performing discovery (assuming the device is within range).</p>
-
+any time without performing discovery (assuming the device is within range).</p>
+
<p>Remember there is a difference between being paired and being connected. To
be paired means that two devices are aware of each other's existence, have a
shared link-key that can be used for authentication, and are capable of
@@ -265,28 +290,28 @@
the devices currently share an RFCOMM channel and are able to transmit data with
each other. The current Android Bluetooth API's require devices to be paired
before an RFCOMM connection can be established. (Pairing is automatically performed
-when you initiate an encrypted connection with the Bluetooth APIs.)</p>
-
+when you initiate an encrypted connection with the Bluetooth APIs.)</p>
+
<p>The following sections describe how to find devices that have been paired, or
-discover new devices using device discovery.</p>
-
+discover new devices using device discovery.</p>
+
<p class="note"><strong>Note:</strong> Android-powered devices are not
discoverable by default. A user can make
the device discoverable for a limited time through the system settings, or an
application can request that the user enable discoverability without leaving the
-application. How to <a href="#EnablingDiscoverability">enable discoverability</a>
-is discussed below.</p>
-
-
-<h3 id="QueryingPairedDevices">Querying paired devices</h3>
-
+application. How to <a href="#EnablingDiscoverability">enable discoverability</a>
+is discussed below.</p>
+
+
+<h3 id="QueryingPairedDevices">Querying paired devices</h3>
+
<p>Before performing device discovery, its worth querying the set
of paired devices to see if the desired device is already known. To do so,
call {@link android.bluetooth.BluetoothAdapter#getBondedDevices()}. This
will return a Set of {@link android.bluetooth.BluetoothDevice}s representing
paired devices. For example, you can query all paired devices and then
-show the name of each device to the user, using an ArrayAdapter:</p>
-<pre>
+show the name of each device to the user, using an ArrayAdapter:</p>
+<pre>
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
@@ -296,24 +321,24 @@
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
-</pre>
-
+</pre>
+
<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
in order to initiate a connection is the MAC address. In this example, it's saved
as a part of an ArrayAdapter that's shown to the user. The MAC address can later
be extracted in order to initiate the connection. You can learn more about creating
-a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
-
-
-<h3 id="DiscoveringDevices">Discovering devices</h3>
-
+a connection in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
+
+
+<h3 id="DiscoveringDevices">Discovering devices</h3>
+
<p>To start discovering devices, simply call {@link
android.bluetooth.BluetoothAdapter#startDiscovery()}. The
process is asynchronous and the method will immediately return with a boolean
indicating whether discovery has successfully started. The discovery process
usually involves an inquiry scan of about 12 seconds, followed by a page scan of
-each found device to retrieve its Bluetooth name.</p>
-
+each found device to retrieve its Bluetooth name.</p>
+
<p>Your application must register a BroadcastReceiver for the
{@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent in
order to receive information about each
@@ -324,8 +349,8 @@
{@link android.bluetooth.BluetoothDevice#EXTRA_CLASS}, containing a
{@link android.bluetooth.BluetoothDevice} and a {@link
android.bluetooth.BluetoothClass}, respectively. For example, here's how you can
-register to handle the broadcast when devices are discovered:</p>
-<pre>
+register to handle the broadcast when devices are discovered:</p>
+<pre>
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
@@ -342,15 +367,15 @@
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
-</pre>
-
+</pre>
+
<p>All that's needed from the {@link android.bluetooth.BluetoothDevice} object
in order to initiate a
connection is the MAC address. In this example, it's saved as a part of an
ArrayAdapter that's shown to the user. The MAC address can later be extracted in
order to initiate the connection. You can learn more about creating a connection
-in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
-
+in the section about <a href="#ConnectingDevices">Connecting Devices</a>.</p>
+
<p class="caution"><strong>Caution:</strong> Performing device discovery is
a heavy procedure for the Bluetooth
adapter and will consume a lot of its resources. Once you have found a device to
@@ -359,41 +384,44 @@
attempting a connection. Also, if you
already hold a connection with a device, then performing discovery can
significantly reduce the bandwidth available for the connection, so you should
-not perform discovery while connected.</p>
-
-<h4 id="EnablingDiscoverability">Enabling discoverability</h4>
-
+not perform discovery while connected.</p>
+
+<h4 id="EnablingDiscoverability">Enabling discoverability</h4>
+
<p>If you would like to make the local device discoverable to other devices,
call {@link android.app.Activity#startActivityForResult(Intent,int)} with the
-{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action Intent.
-This will issue a request to enable discoverable mode through the system settings (without
-stopping your application). By default, the device will become discoverable for
-120 seconds. You can define a different duration by adding the
-{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent extra
-(maximum duration is 300 seconds). For example:</p>
-<pre>
-Intent discoverableIntent = new
+{@link android.bluetooth.BluetoothAdapter#ACTION_REQUEST_DISCOVERABLE} action
+Intent. This will issue a request to enable discoverable mode through the system
+settings (without stopping your application). By default, the device will become
+discoverable for 120 seconds. You can define a different duration by adding the
+{@link android.bluetooth.BluetoothAdapter#EXTRA_DISCOVERABLE_DURATION} Intent
+extra. The maximum duration an app can set is 3600 seconds, and a value of 0
+means the device is always discoverable. Any value below 0 or above 3600 is
+automatically set to 120 secs). For example, this snippet sets the duration to
+300:</p>
+
+<pre>Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
-</pre>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_enable_discoverable.png" />
+</pre>
+
+<div class="figure" style="width:200px">
+<img src="{@docRoot}images/bt_enable_discoverable.png" />
<strong>Figure 2:</strong> The enabling discoverability dialog.
-</div>
-
+</div>
+
<p>A dialog will be displayed, requesting user permission to make the device
discoverable, as shown in Figure 2. If the user responds "Yes," then the device
will become discoverable for the specified amount of time. Your Activity will
then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent)
onActivityResult())} callback, with the result code equal to the duration that the device
is discoverable. If the user responded "No" or if an error occurred, the result code will
-be Activity.RESULT_CANCELLED.</p>
-
+be Activity.RESULT_CANCELLED.</p>
+
<p class="note"><strong>Note:</strong> If Bluetooth has not been enabled on the device,
-then enabling device discoverability will automatically enable Bluetooth.</p>
-
+then enabling device discoverability will automatically enable Bluetooth.</p>
+
<p>The device will silently remain in discoverable mode for the allotted time.
If you would like to be notified when the discoverable mode has changed, you can
register a BroadcastReceiver for the {@link
@@ -407,18 +435,18 @@
android.bluetooth.BluetoothAdapter#SCAN_MODE_NONE},
which indicate that the device is either in discoverable mode, not in
discoverable mode but still able to receive connections, or not in discoverable
-mode and unable to receive connections, respectively.</p>
-
+mode and unable to receive connections, respectively.</p>
+
<p>You do not need to enable device discoverability if you will be initiating
the connection to a remote device. Enabling discoverability is only necessary when
you want your application to host a server socket that will accept incoming
connections, because the remote devices must be able to discover the device
-before it can initiate the connection.</p>
-
-
-
-<h2 id="ConnectingDevices">Connecting Devices</h2>
-
+before it can initiate the connection.</p>
+
+
+
+<h2 id="ConnectingDevices">Connecting Devices</h2>
+
<p>In order to create a connection between your application on two devices, you
must implement both the server-side and client-side mechanisms, because one
device must open a server socket and the other one must initiate the connection
@@ -428,36 +456,36 @@
point, each device can obtain input and output streams and data transfer can
begin, which is discussed in the section about <a
href="#ManagingAConnection">Managing a Connection</a>. This section describes how
-to initiate the connection between two devices.</p>
-
+to initiate the connection between two devices.</p>
+
<p>The server device and the client device each obtain the required {@link
android.bluetooth.BluetoothSocket} in different ways. The server will receive it
when an incoming connection is accepted. The client will receive it when it
-opens an RFCOMM channel to the server.</p>
-
-<div class="figure" style="width:200px">
-<img src="{@docRoot}images/bt_pairing_request.png" />
+opens an RFCOMM channel to the server.</p>
+
+<div class="figure" style="width:200px">
+<img src="{@docRoot}images/bt_pairing_request.png" />
<strong>Figure 3:</strong> The Bluetooth pairing dialog.
-</div>
-
+</div>
+
<p>One implementation technique is to automatically prepare each device as a
server, so that each one has a server socket open and listening for connections.
Then either device can initiate a connection with the other and become the
client. Alternatively, one device can explicitly "host" the connection and open
a server socket on demand and the other device can simply initiate the
-connection.</p>
-
+connection.</p>
+
<p class="note"><strong>Note:</strong> If the two devices have not been previously paired,
then the Android framework will automatically show a pairing request notification or
dialog to the user during the connection procedure, as shown in Figure 3. So
when attempting to connect devices,
your application does not need to be concerned about whether or not the devices are
paired. Your RFCOMM connection attempt will block until the user has successfully paired,
-or will fail if the user rejects pairing, or if pairing fails or times out. </p>
-
-
-<h3 id="ConnectingAsAServer">Connecting as a server</h3>
-
+or will fail if the user rejects pairing, or if pairing fails or times out. </p>
+
+
+<h3 id="ConnectingAsAServer">Connecting as a server</h3>
+
<p>When you want to connect two devices, one must act as a server by holding an
open {@link android.bluetooth.BluetoothServerSocket}. The purpose of the server
socket is to listen for incoming connection requests and when one is accepted,
@@ -465,26 +493,26 @@
android.bluetooth.BluetoothSocket} is acquired from the {@link
android.bluetooth.BluetoothServerSocket},
the {@link android.bluetooth.BluetoothServerSocket} can (and should) be
-discarded, unless you want to accept more connections.</p>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>About UUID</h2>
-
+discarded, unless you want to accept more connections.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>About UUID</h2>
+
<p>A Universally Unique Identifier (UUID) is a standardized 128-bit format for a string
ID used to uniquely identify information. The point of a UUID is that it's big
enough that you can select any random and it won't clash. In this case, it's
used to uniquely identify your application's Bluetooth service. To get a UUID to
use with your application, you can use one of the many random UUID generators on
the web, then initialize a {@link java.util.UUID} with {@link
-java.util.UUID#fromString(String)}.</p>
-</div>
-</div>
-
+java.util.UUID#fromString(String)}.</p>
+</div>
+</div>
+
<p>Here's the basic procedure to set up a server socket and accept a
-connection:</p>
-
-<ol>
+connection:</p>
+
+<ol>
<li>Get a {@link android.bluetooth.BluetoothServerSocket} by calling the
{@link
android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
@@ -496,9 +524,9 @@
agreement with the client device. That is, when the client attempts to connect
with this device, it will carry a UUID that uniquely identifies the service with
which it wants to connect. These UUIDs must match in order for the connection to
-be accepted (in the next step).</p>
-</li>
-
+be accepted (in the next step).</p>
+</li>
+
<li>Start listening for connection requests by calling
{@link android.bluetooth.BluetoothServerSocket#accept()}.
<p>This is a blocking call. It will return when either a connection has been
@@ -506,9 +534,9 @@
remote device has sent a connection request with a UUID matching the one
registered with this listening server socket. When successful, {@link
android.bluetooth.BluetoothServerSocket#accept()} will
-return a connected {@link android.bluetooth.BluetoothSocket}.</p>
-</li>
-
+return a connected {@link android.bluetooth.BluetoothSocket}.</p>
+</li>
+
<li>Unless you want to accept additional connections, call
{@link android.bluetooth.BluetoothServerSocket#close()}.
<p>This releases the server socket and all its resources, but does <em>not</em> close the
@@ -517,10 +545,10 @@
connected client per channel at a time, so in most cases it makes sense to call {@link
android.bluetooth.BluetoothServerSocket#close()} on the {@link
android.bluetooth.BluetoothServerSocket} immediately after accepting a connected
-socket.</p>
-</li>
-</ol>
-
+socket.</p>
+</li>
+</ol>
+
<p>The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not
be executed in the main Activity UI thread because it is a blocking call and
will prevent any other interaction with the application. It usually makes
@@ -533,16 +561,16 @@
android.bluetooth.BluetoothSocket}) from another thread and the blocked call will
immediately return. Note that all methods on a {@link
android.bluetooth.BluetoothServerSocket} or {@link android.bluetooth.BluetoothSocket}
-are thread-safe.</p>
-
-<h4>Example</h4>
-
+are thread-safe.</p>
+
+<h4>Example</h4>
+
<p>Here's a simplified thread for the server component that accepts incoming
-connections:</p>
-<pre>
+connections:</p>
+<pre>
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
-
+
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
@@ -553,7 +581,7 @@
} catch (IOException e) { }
mmServerSocket = tmp;
}
-
+
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
@@ -572,7 +600,7 @@
}
}
}
-
+
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
@@ -580,37 +608,37 @@
} catch (IOException e) { }
}
}
-</pre>
-
+</pre>
+
<p>In this example, only one incoming connection is desired, so as soon as a
connection is accepted and the {@link android.bluetooth.BluetoothSocket} is
acquired, the application
sends the acquired {@link android.bluetooth.BluetoothSocket} to a separate
thread, closes the
-{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p>
-
+{@link android.bluetooth.BluetoothServerSocket} and breaks the loop.</p>
+
<p>Note that when {@link android.bluetooth.BluetoothServerSocket#accept()}
returns the {@link android.bluetooth.BluetoothSocket}, the socket is already
connected, so you should <em>not</em> call {@link
android.bluetooth.BluetoothSocket#connect()} (as you do from the
-client-side).</p>
-
+client-side).</p>
+
<p><code>manageConnectedSocket()</code> is a fictional method in the application
that will
initiate the thread for transferring data, which is discussed in the section
-about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
-
+about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
+
<p>You should usually close your {@link android.bluetooth.BluetoothServerSocket}
as soon as you are done listening for incoming connections. In this example, {@link
android.bluetooth.BluetoothServerSocket#close()} is called as soon
as the {@link android.bluetooth.BluetoothSocket} is acquired. You may also want
to provide a public method in your thread that can close the private {@link
android.bluetooth.BluetoothSocket} in the event that you need to stop listening on the
-server socket.</p>
-
-
-<h3 id="ConnectingAsAClient">Connecting as a client</h3>
-
+server socket.</p>
+
+
+<h3 id="ConnectingAsAClient">Connecting as a client</h3>
+
<p>In order to initiate a connection with a remote device (a device holding an
open
server socket), you must first obtain a {@link
@@ -619,11 +647,11 @@
section about <a
href="#FindingDevices">Finding Devices</a>.) You must then use the
{@link android.bluetooth.BluetoothDevice} to acquire a {@link
-android.bluetooth.BluetoothSocket} and initiate the connection.</p>
-
-<p>Here's the basic procedure:</p>
-
-<ol>
+android.bluetooth.BluetoothSocket} and initiate the connection.</p>
+
+<p>Here's the basic procedure:</p>
+
+<ol>
<li>Using the {@link android.bluetooth.BluetoothDevice}, get a {@link
android.bluetooth.BluetoothSocket} by calling {@link
android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(UUID)}.
@@ -634,9 +662,9 @@
android.bluetooth.BluetoothAdapter#listenUsingRfcommWithServiceRecord(String,
UUID)}). Using the same UUID is simply a matter of hard-coding the UUID string
into your application and then referencing it from both the server and client
-code.</p>
-</li>
-
+code.</p>
+</li>
+
<li>Initiate the connection by calling {@link
android.bluetooth.BluetoothSocket#connect()}.
<p>Upon this call, the system will perform an SDP lookup on the remote device in
@@ -647,34 +675,34 @@
blocking call. If, for
any reason, the connection fails or the {@link
android.bluetooth.BluetoothSocket#connect()} method times out (after about
-12 seconds), then it will throw an exception.</p>
+12 seconds), then it will throw an exception.</p>
<p>Because {@link
android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection
procedure should always be performed in a thread separate from the main Activity
-thread.</p>
+thread.</p>
<p class="note">Note: You should always ensure that the device is not performing
device discovery when you call {@link
android.bluetooth.BluetoothSocket#connect()}. If discovery is in progress, then
the
-connection attempt will be significantly slowed and is more likely to fail.</p>
-</li>
-</ol>
-
-<h4>Example</h4>
-
+connection attempt will be significantly slowed and is more likely to fail.</p>
+</li>
+</ol>
+
+<h4>Example</h4>
+
<p>Here is a basic example of a thread that initiates a Bluetooth
-connection:</p>
-<pre>
+connection:</p>
+<pre>
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
-
+
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
-
+
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
@@ -682,11 +710,11 @@
} catch (IOException e) { }
mmSocket = tmp;
}
-
+
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
-
+
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
@@ -698,11 +726,11 @@
} catch (IOException closeException) { }
return;
}
-
+
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
-
+
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
@@ -710,42 +738,42 @@
} catch (IOException e) { }
}
}
-</pre>
-
+</pre>
+
<p>Notice that {@link android.bluetooth.BluetoothAdapter#cancelDiscovery()} is called
before the connection is made. You should always do this before connecting and it is safe
to call without actually checking whether it is running or not (but if you do want to
-check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p>
-
+check, call {@link android.bluetooth.BluetoothAdapter#isDiscovering()}).</p>
+
<p><code>manageConnectedSocket()</code> is a fictional method in the application
that will initiate the thread for transferring data, which is discussed in the section
-about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
-
+about <a href="#ManagingAConnection">Managing a Connection</a>.</p>
+
<p>When you're done with your {@link android.bluetooth.BluetoothSocket}, always
call {@link android.bluetooth.BluetoothSocket#close()} to clean up.
Doing so will immediately close the connected socket and clean up all internal
-resources.</p>
-
-
-<h2 id="ManagingAConnection">Managing a Connection</h2>
-
+resources.</p>
+
+
+<h2 id="ManagingAConnection">Managing a Connection</h2>
+
<p>When you have successfully connected two (or more) devices, each one will
have a connected {@link android.bluetooth.BluetoothSocket}. This is where the fun
begins because you can share data between devices. Using the {@link
android.bluetooth.BluetoothSocket}, the general procedure to transfer arbitrary data is
-simple:</p>
-<ol>
+simple:</p>
+<ol>
<li>Get the {@link java.io.InputStream} and {@link java.io.OutputStream} that
handle transmissions through the socket, via {@link
android.bluetooth.BluetoothSocket#getInputStream()} and
-{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li>
-
+{@link android.bluetooth.BluetoothSocket#getOutputStream}, respectively.</li>
+
<li>Read and write data to the streams with {@link
-java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li>
-</ol>
-
-<p>That's it.</p>
-
+java.io.InputStream#read(byte[])} and {@link java.io.OutputStream#write(byte[])}.</li>
+</ol>
+
+<p>That's it.</p>
+
<p>There are, of course, implementation details to consider. First and foremost,
you should use a dedicated thread for all stream reading and writing. This is
important because both {@link java.io.InputStream#read(byte[])} and {@link
@@ -756,37 +784,37 @@
java.io.InputStream#read(byte[])} quickly enough and the intermediate buffers are full.
So, your main loop in the thread should be dedicated to reading from the {@link
java.io.InputStream}. A separate public method in the thread can be used to initiate
-writes to the {@link java.io.OutputStream}.</p>
-
-<h4>Example</h4>
-
-<p>Here's an example of how this might look:</p>
-<pre>
+writes to the {@link java.io.OutputStream}.</p>
+
+<h4>Example</h4>
+
+<p>Here's an example of how this might look:</p>
+<pre>
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
-
+
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
-
+
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
-
+
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
-
+
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
-
+
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
@@ -800,14 +828,14 @@
}
}
}
-
+
/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
-
+
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
@@ -815,27 +843,124 @@
} catch (IOException e) { }
}
}
-</pre>
-
+</pre>
+
<p>The constructor acquires the necessary streams and once executed, the thread
will wait for data to come through the InputStream. When {@link
java.io.InputStream#read(byte[])} returns with
bytes from the stream, the data is sent to the main Activity using a member
Handler from the parent class. Then it goes back and waits for more bytes from
-the stream.</p>
-
+the stream.</p>
+
<p>Sending outgoing data is as simple as calling the thread's
<code>write()</code> method from the main Activity and passing in the bytes to
be sent. This method then simply calls {@link
-java.io.OutputStream#write(byte[])} to send the data to the remote device.</p>
-
+java.io.OutputStream#write(byte[])} to send the data to the remote device.</p>
+
<p>The thread's <code>cancel()</code> method is important so that the connection
can be
terminated at any time by closing the {@link android.bluetooth.BluetoothSocket}.
This should always be called when you're done using the Bluetooth
-connection.</p>
+connection.</p>
+
+<div class="special">
+<p>For a demonstration of using the Bluetooth APIs, see the <a
+href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p>
+</div>
-<div class="special">
-<p>For a complete demonstration using the Bluetooth APIs, see the <a
-href="{@docRoot}resources/samples/BluetoothChat/index.html">Bluetooth Chat sample app</a>.</p>
-</div>
+<h2 id="Profiles">Working with Profiles</h2>
+
+<p>Starting in Android 3.0, the Bluetooth API includes support for working with
+Bluetooth profiles. A <em>Bluetooth profile</em> is a wireless interface
+specification for Bluetooth-based communication between devices. An example
+is the Hands-Free profile. For a mobile phone to connect to a wireless headset,
+both devices must support the Hands-Free profile. </p>
+
+<p>You can implement the interface {@link android.bluetooth.BluetoothProfile} to write
+your own classes to support a particular Bluetooth profile. The Android
+Bluetooth API provides implementations for the following Bluetooth
+profiles:</p>
+<ul>
+
+ <li><strong>Headset</strong>. The Headset profile provides support for
+Bluetooth headsets to be used with mobile phones. Android provides the {@link
+android.bluetooth.BluetoothHeadset} class, which is a proxy for controlling the
+Bluetooth Headset Service via interprocess communication (<a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#IPC">IPC</a
+>). This includes both Bluetooth Headset and Hands-Free (v1.5) profiles. The
+{@link android.bluetooth.BluetoothHeadset} class includes support for AT commands.
+For more discussion of this topic, see <a href="#AT-Commands">Vendor-specific AT commands</a></li>
+
+ <li><strong>A2DP</strong>. The Advanced Audio Distribution Profile (A2DP)
+profile defines how high quality audio can be streamed from one device to
+another over a Bluetooth connection. Android provides the {@link
+android.bluetooth.BluetoothA2dp} class, which is a proxy for controlling
+the Bluetooth A2DP Service via IPC.</li>
+
+</ul>
+
+<p>Here are the basic steps for working with a profile:</p>
+<ol>
+
+ <li>Get the default adapter, as described in <a href="{@docRoot}guide/topics/wireless/bluetooth.
+html#SettingUp">Setting Up Bluetooth</a>.</li>
+
+ <li>Use {@link
+android.bluetooth.BluetoothAdapter#getProfileProxy(android.content.Context,
+android.bluetooth.BluetoothProfile.ServiceListener, int) getProfileProxy()} to
+establish a connection to the profile proxy object associated with the profile.
+In the example below, the profile proxy object is an instance of {@link
+android.bluetooth.BluetoothHeadset}. </li>
+
+ <li>Set up a {@link android.bluetooth.BluetoothProfile.ServiceListener}. This
+listener notifies {@link android.bluetooth.BluetoothProfile} IPC clients when
+they have been connected to or disconnected from the service.</li>
+
+ <li>In {@link
+android.bluetooth.BluetoothProfile.ServiceListener#onServiceConnected(int,
+android.bluetooth.BluetoothProfile) onServiceConnected()}, get a handle
+to the profile proxy object.</li>
+
+ <li>Once you have the profile proxy object, you can use it to monitor the
+state of the connection and perform other operations that are relevant to that
+profile.</li>
+</ol>
+<p> For example, this code snippet shows how to connect to a {@link android.bluetooth.BluetoothHeadset} proxy object so that you can control the
+Headset profile:</p>
+
+<pre>BluetoothHeadset mBluetoothHeadset;
+
+// Get the default adapter
+BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+// Establish connection to the proxy.
+mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
+
+private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (profile == BluetoothProfile.HEADSET) {
+ mBluetoothHeadset = (BluetoothHeadset) proxy;
+ }
+ }
+ public void onServiceDisconnected(int profile) {
+ if (profile == BluetoothProfile.HEADSET) {
+ mBluetoothHeadset = null;
+ }
+ }
+};
+
+// ... call functions on mBluetoothHeadset
+
+// Close proxy connection after use.
+mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
+</pre>
+
+<h3 id="AT-Commands">Vendor-specific AT commands</h3>
+
+<p>Starting in Android 3.0, applications can register to receive system
+broadcasts of pre-defined vendor-specific AT commands sent by headsets (such as
+a Plantronics +XEVENT command). For example, an application could receive
+broadcasts that indicate a connected device's battery level and could notify the
+user or take other action as needed. Create a broadcast receiver for the {@link
+android.bluetooth.BluetoothHeadset#ACTION_VENDOR_SPECIFIC_HEADSET_EVENT} intent
+to handle vendor-specific AT commands for the headset.</p>
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index 097d004..e8c9ae7 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -547,6 +547,16 @@
}
},
{
+ tags: ['sample', 'new', 'media' ],
+ path: 'samples/RandomMusicPlayer/index.html',
+ title: {
+ en: 'Random Music Player'
+ },
+ description: {
+ en: 'Demonstrates how to write a multimedia application that plays music from the device and from URLs. It manages media playback from a service and can play music in the background, respecting audio focus changes.'
+ }
+ },
+ {
tags: ['sample', 'new', 'newfeature', 'performance', 'gamedev', 'gl'],
path: 'samples/RenderScript/index.html',
title: {
diff --git a/docs/html/resources/samples/images/randommusicplayer.png b/docs/html/resources/samples/images/randommusicplayer.png
new file mode 100644
index 0000000..e16e067
--- /dev/null
+++ b/docs/html/resources/samples/images/randommusicplayer.png
Binary files differ
diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd
index 7a3a9c3..e9dc20f 100644
--- a/docs/html/resources/tutorials/views/hello-spinner.jd
+++ b/docs/html/resources/tutorials/views/hello-spinner.jd
@@ -105,7 +105,7 @@
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
- Toast.makeText(parent.getContext()), "The planet is " +
+ Toast.makeText(parent.getContext(), "The planet is " +
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
}
diff --git a/docs/html/sdk/android-3.1-highlights.jd b/docs/html/sdk/android-3.1-highlights.jd
index 3d132a3..88bc1ee 100644
--- a/docs/html/sdk/android-3.1-highlights.jd
+++ b/docs/html/sdk/android-3.1-highlights.jd
@@ -143,8 +143,8 @@
<p>To make the platform even better for gaming, Android 3.1 adds support for
most PC joysticks and gamepads that are connected over USB or Bluetooth HID.</p>
-<p>For example, users can connect Sony Playstation™ 3 and XBox 360™ game
-controllers over USB (but not Bluetooth), Logitech Dual Action™ gamepads and
+<p>For example, users can connect PlayStation<sup>®</sup>3 and Xbox 360<sup>®</sup>
+game controllers over USB (but not Bluetooth), Logitech Dual Action™ gamepads and
flight sticks, or a car racing controller. Game controllers that use proprietary
networking or pairing are not supported by default, but in general, the platform
supports most PC-connectible joysticks and gamepads.</p>
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index 27e742a..3c2ba8b 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -80,6 +80,12 @@
<td><a href="http://www.kyocera-wireless.com/support/phone_drivers.htm">http://www.kyocera-wireless.com/support/phone_drivers.htm</a>
</td>
</tr>
+ <tr>
+ <td>Lenevo</td>
+ <td><a href="http://developer.lenovomm.com/developer/download.jsp"
+ >http://developer.lenovomm.com/developer/download.jsp</a>
+ </td>
+ </tr>
<tr><td>LGE</td> <td><a
href="http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp">http://www.lg.com/us/mobile-phones/mobile-support/mobile-lg-mobile-phone-support.jsp</a></td>
</tr><tr><td>Motorola</td> <td><a
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 5750c81..d02c13d 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -175,7 +175,8 @@
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5c</a>
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r5c <span
+ class="new">new!</span></a>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
</ul>
diff --git a/docs/html/search.jd b/docs/html/search.jd
index 609ade9..339ce2d 100644
--- a/docs/html/search.jd
+++ b/docs/html/search.jd
@@ -1,144 +1,140 @@
page.title=Search Results
@jd:body
-<script src="http://www.google.com/jsapi" type="text/javascript"></script>
+<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script src="{@docRoot}assets/jquery-history.js" type="text/javascript"></script>
-<script type="text/javascript">
- var tabIndex = 0;
-
- google.load('search', '1');
-
- function OnLoad() {
- document.getElementById("search_autocomplete").style.color = "#000";
-
- // create search control
- searchControl = new google.search.SearchControl();
-
- // use our existing search form and use tabs when multiple searchers are used
- drawOptions = new google.search.DrawOptions();
- drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);
- drawOptions.setInput(document.getElementById("search_autocomplete"));
-
- // configure search result options
- searchOptions = new google.search.SearcherOptions();
- searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
-
- // configure each of the searchers, for each tab
- devSiteSearcher = new google.search.WebSearch();
- devSiteSearcher.setUserDefinedLabel("All Developers Site");
- devSiteSearcher.setSiteRestriction("http://developer.android.com/");
-
- devGuideSearcher = new google.search.WebSearch();
- devGuideSearcher.setUserDefinedLabel("Dev Guide");
- devGuideSearcher.setSiteRestriction("http://developer.android.com/guide/");
-
- referenceSearcher = new google.search.WebSearch();
- referenceSearcher.setUserDefinedLabel("Reference");
- referenceSearcher.setSiteRestriction("http://developer.android.com/reference/");
-
- blogSearcher = new google.search.WebSearch();
- blogSearcher.setUserDefinedLabel("Blog");
- blogSearcher.setSiteRestriction("http://android-developers.blogspot.com");
-
- groupsSearcher = new google.search.WebSearch();
- groupsSearcher.setUserDefinedLabel("Developer Groups");
- groupsSearcher.setSiteRestriction("001283715400630100512:ggqrtvkztwm");
-
- sourceSiteSearcher = new google.search.WebSearch();
- sourceSiteSearcher.setUserDefinedLabel("Android Source");
- sourceSiteSearcher.setSiteRestriction("http://source.android.com");
-
- homeSiteSearcher = new google.search.WebSearch();
- homeSiteSearcher.setUserDefinedLabel("Android Home");
- homeSiteSearcher.setSiteRestriction("http://www.android.com");
-
- // add each searcher to the search control
- searchControl.addSearcher(devSiteSearcher, searchOptions);
- searchControl.addSearcher(devGuideSearcher, searchOptions);
- searchControl.addSearcher(referenceSearcher, searchOptions);
- searchControl.addSearcher(groupsSearcher, searchOptions);
- searchControl.addSearcher(sourceSiteSearcher, searchOptions);
- searchControl.addSearcher(blogSearcher, searchOptions);
-
- // configure result options
- searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
- searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
- searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_LONG);
- searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING);
-
- // upon ajax search, refresh the url and search title
- searchControl.setSearchStartingCallback(this, function(control, searcher, query) {
- // save the tab index from the hash
- tabIndex = location.hash.split("&t=")[1];
-
- $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
- $.history.add('q=' + query + '&t=' + tabIndex);
- openTab();
- });
-
- // draw the search results box
- searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
-
- // get query and execute the search
- if (location.hash.indexOf("&t=") != -1) {
- searchControl.execute(decodeURI(getQuery(location.hash)));
- }
-
- document.getElementById("search_autocomplete").focus();
- addTabListeners();
- }
- // End of OnLoad
-
-
- google.setOnLoadCallback(OnLoad, true);
-
- // when an event on the browser history occurs (back, forward, load) perform a search
- $(window).history(function(e, hash) {
- var query = decodeURI(getQuery(hash));
- searchControl.execute(query);
-
- $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
- });
-
- // forcefully regain key-up event control (previously jacked by search api)
- $("#search_autocomplete").keyup(function(event) {
- return search_changed(event, false, '/');
- });
-
- // open a tab, specified by its array position
- function openTab() {
- tabIndex = location.hash.split("&t=")[1];
-
- // show the appropriate tab
- var tabHeaders = $(".gsc-tabHeader");
- $(tabHeaders[tabIndex]).click();
- }
-
- // add event listeners to each tab so we can track the browser history
- function addTabListeners() {
- var tabHeaders = $(".gsc-tabHeader");
- for (var i = 0; i < tabHeaders.length; i++) {
- $(tabHeaders[i]).attr("id",i).click(function() {
- var tabHeaders = $(".gsc-tabHeader");
+<script type="text/javascript">
+ var tabIndex = 0;
+
+ google.load('search', '1');
+
+ function OnLoad() {
+ document.getElementById("search_autocomplete").style.color = "#000";
+
+ // create search control
+ searchControl = new google.search.SearchControl();
+
+ // use our existing search form and use tabs when multiple searchers are used
+ drawOptions = new google.search.DrawOptions();
+ drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);
+ drawOptions.setInput(document.getElementById("search_autocomplete"));
+
+ // configure search result options
+ searchOptions = new google.search.SearcherOptions();
+ searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
+
+ // configure each of the searchers, for each tab
+ devSiteSearcher = new google.search.WebSearch();
+ devSiteSearcher.setUserDefinedLabel("All");
+ devSiteSearcher.setSiteRestriction("001482626316274216503:zu90b7s047u");
+
+ devGuideSearcher = new google.search.WebSearch();
+ devGuideSearcher.setUserDefinedLabel("Dev Guide");
+ devGuideSearcher.setSiteRestriction("http://developer.android.com/guide/");
+
+ referenceSearcher = new google.search.WebSearch();
+ referenceSearcher.setUserDefinedLabel("Reference");
+ referenceSearcher.setSiteRestriction("http://developer.android.com/reference/");
+
+ blogSearcher = new google.search.WebSearch();
+ blogSearcher.setUserDefinedLabel("Blog");
+ blogSearcher.setSiteRestriction("http://android-developers.blogspot.com");
+
+ groupsSearcher = new google.search.WebSearch();
+ groupsSearcher.setUserDefinedLabel("Developer Groups");
+ groupsSearcher.setSiteRestriction("001283715400630100512:ggqrtvkztwm");
+
+ sourceSiteSearcher = new google.search.WebSearch();
+ sourceSiteSearcher.setUserDefinedLabel("Android Source");
+ sourceSiteSearcher.setSiteRestriction("http://source.android.com");
+
+ // add each searcher to the search control
+ searchControl.addSearcher(devSiteSearcher, searchOptions);
+ searchControl.addSearcher(devGuideSearcher, searchOptions);
+ searchControl.addSearcher(referenceSearcher, searchOptions);
+ searchControl.addSearcher(groupsSearcher, searchOptions);
+ searchControl.addSearcher(sourceSiteSearcher, searchOptions);
+ searchControl.addSearcher(blogSearcher, searchOptions);
+
+ // configure result options
+ searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
+ searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
+ searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_LONG);
+ searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING);
+
+ // upon ajax search, refresh the url and search title
+ searchControl.setSearchStartingCallback(this, function(control, searcher, query) {
+ // save the tab index from the hash
+ tabIndex = location.hash.split("&t=")[1];
+
+ $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
+ $.history.add('q=' + query + '&t=' + tabIndex);
+ openTab();
+ });
+
+ // draw the search results box
+ searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
+
+ // get query and execute the search
+ if (location.hash.indexOf("&t=") != -1) {
+ searchControl.execute(decodeURI(getQuery(location.hash)));
+ }
+
+ document.getElementById("search_autocomplete").focus();
+ addTabListeners();
+ }
+ // End of OnLoad
+
+
+ google.setOnLoadCallback(OnLoad, true);
+
+ // when an event on the browser history occurs (back, forward, load) perform a search
+ $(window).history(function(e, hash) {
+ var query = decodeURI(getQuery(hash));
+ searchControl.execute(query);
+
+ $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
+ });
+
+ // forcefully regain key-up event control (previously jacked by search api)
+ $("#search_autocomplete").keyup(function(event) {
+ return search_changed(event, false, '/');
+ });
+
+ // open a tab, specified by its array position
+ function openTab() {
+ tabIndex = location.hash.split("&t=")[1];
+
+ // show the appropriate tab
+ var tabHeaders = $(".gsc-tabHeader");
+ $(tabHeaders[tabIndex]).click();
+ }
+
+ // add event listeners to each tab so we can track the browser history
+ function addTabListeners() {
+ var tabHeaders = $(".gsc-tabHeader");
+ for (var i = 0; i < tabHeaders.length; i++) {
+ $(tabHeaders[i]).attr("id",i).click(function() {
+ var tabHeaders = $(".gsc-tabHeader");
var tabIndex = $(this).attr("id");
- $.history.add('q=' + getQuery(location.hash) + '&t=' + tabIndex); // update the hash with the new tab
- });
- }
- }
-
+ $.history.add('q=' + getQuery(location.hash) + '&t=' + tabIndex); // update the hash with the new tab
+ });
+ }
+ }
+
function getQuery(hash) {
- var hashParts = hash.split('&t=');
- var queryParts = hashParts[0].split('=');
- return queryParts[1];
- }
-
- /* returns the given string with all HTML brackets converted to entities
- TODO: move this to the site's JS library */
- function escapeHTML(string) {
- return string.replace(/</g,"<")
- .replace(/>/g,">");
- }
-
+ var hashParts = hash.split('&t=');
+ var queryParts = hashParts[0].split('=');
+ return queryParts[1];
+ }
+
+ /* returns the given string with all HTML brackets converted to entities
+ TODO: move this to the site's JS library */
+ function escapeHTML(string) {
+ return string.replace(/</g,"<")
+ .replace(/>/g,">");
+ }
+
</script>
<div id="mainBodyFixed" style="width:auto; margin:20px">
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index 3dee435..5400bdd 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -43,6 +43,10 @@
}
bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const {
+ if (String8("") == mimeType) {
+ return false;
+ }
+
for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) {
const String8 item = mMimeTypeVector.itemAt(i);
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 458f1b6..2d8e877 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -107,6 +107,7 @@
handle->decryptInfo = NULL;
}
handle->copyControlVector.clear();
+ handle->extendedData.clear();
}
int BpDrmManagerService::addUniqueId(int uniqueId) {
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
index 5907956..ef9c21d 100755
--- a/drm/java/android/drm/DrmRights.java
+++ b/drm/java/android/drm/DrmRights.java
@@ -107,31 +107,24 @@
/**
* Creates a <code>DrmRights</code> object with the given parameters.
- *<p>
- * The application can pass the processed data as a <code>String</code> or as binary data.
- *<p>
- * The following code snippet shows how to pass the processed data as a <code>String</code>:
- *<p>
- * new DrmRights(data.getBytes(), mimeType)
- *<p>
- * The following code snippet shows how to pass the processed data as binary data:
- *<p>
- * new DrmRights(binaryData[], mimeType)
*
- * @param data A {@link ProcessedData} object.
+ * @param data A {@link ProcessedData} object containing rights information.
+ * data could be null because it's optional for some DRM schemes.
* @param mimeType The MIME type.
*/
public DrmRights(ProcessedData data, String mimeType) {
- mData = data.getData();
+ if (data != null) {
+ mData = data.getData();
- String accountId = data.getAccountId();
- if (null != accountId && !accountId.equals("")) {
- mAccountId = accountId;
- }
+ String accountId = data.getAccountId();
+ if (null != accountId && !accountId.equals("")) {
+ mAccountId = accountId;
+ }
- String subscriptionId = data.getSubscriptionId();
- if (null != subscriptionId && !subscriptionId.equals("")) {
- mSubscriptionId = subscriptionId;
+ String subscriptionId = data.getSubscriptionId();
+ if (null != subscriptionId && !subscriptionId.equals("")) {
+ mSubscriptionId = subscriptionId;
+ }
}
mMimeType = mimeType;
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a57dd98..a36bd4a 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -145,7 +145,6 @@
status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
const String8& rightsPath, const String8& contentPath) {
- status_t status = DRM_ERROR_UNKNOWN;
return getDrmManagerService()->saveRights(
uniqueId, drmRights, rightsPath, contentPath);
}
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index 07b3b47..31c3c14 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -512,6 +512,19 @@
}
}
+ if (NULL != decryptHandle) {
+ if (NULL != decryptHandle->decryptInfo) {
+ delete decryptHandle->decryptInfo;
+ decryptHandle->decryptInfo = NULL;
+ }
+
+ decryptHandle->copyControlVector.clear();
+ decryptHandle->extendedData.clear();
+
+ delete decryptHandle;
+ decryptHandle = NULL;
+ }
+
LOGV("FwdLockEngine::onCloseDecryptSession Exit");
return result;
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 12dc93c..40d54bb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -681,7 +681,8 @@
*/
public enum CompressFormat {
JPEG (0),
- PNG (1);
+ PNG (1),
+ WEBP (2);
CompressFormat(int nativeInt) {
this.nativeInt = nativeInt;
diff --git a/graphics/java/android/graphics/ParcelSurfaceTexture.java b/graphics/java/android/graphics/ParcelSurfaceTexture.java
index 5272cc6..cc8bd02 100644
--- a/graphics/java/android/graphics/ParcelSurfaceTexture.java
+++ b/graphics/java/android/graphics/ParcelSurfaceTexture.java
@@ -19,6 +19,7 @@
import android.graphics.SurfaceTexture;
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.Surface;
/**
*
@@ -34,6 +35,17 @@
private int mISurfaceTexture;
/**
+ * Create a new ParcelSurfaceTexture from a Surface
+ *
+ * @param surface The Surface to create a ParcelSurfaceTexture from.
+ *
+ * @return Returns a new ParcelSurfaceTexture for the given Surface.
+ */
+ public static ParcelSurfaceTexture fromSurface(Surface surface) {
+ return new ParcelSurfaceTexture(surface);
+ }
+
+ /**
* Create a new ParcelSurfaceTexture from a SurfaceTexture
*
* @param surfaceTexture The SurfaceTexture to transport.
@@ -75,8 +87,11 @@
private ParcelSurfaceTexture(Parcel in) {
nativeReadFromParcel(in);
}
+ private ParcelSurfaceTexture(Surface surface) {
+ nativeInitFromSurface(surface);
+ }
private ParcelSurfaceTexture(SurfaceTexture surfaceTexture) {
- nativeInit(surfaceTexture);
+ nativeInitFromSurfaceTexture(surfaceTexture);
}
@Override
@@ -88,7 +103,8 @@
}
}
- private native void nativeInit(SurfaceTexture surfaceTexture);
+ private native void nativeInitFromSurface(Surface surface);
+ private native void nativeInitFromSurfaceTexture(SurfaceTexture surfaceTexture);
private native void nativeFinalize();
private native void nativeWriteToParcel(Parcel dest, int flags);
private native void nativeReadFromParcel(Parcel in);
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 6c7341f..90a7ac2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -93,6 +93,19 @@
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
*/
public SurfaceTexture(int texName) {
+ this(texName, true);
+ }
+
+ /**
+ * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
+ *
+ * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
+ * @param allowSynchronousMode whether the SurfaceTexture can run in the synchronous mode.
+ * When the image stream comes from OpenGL, SurfaceTexture may run in the synchronous
+ * mode where the producer side may be blocked to avoid skipping frames. To avoid the
+ * thread block, set allowSynchronousMode to false.
+ */
+ public SurfaceTexture(int texName, boolean allowSynchronousMode) {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(looper);
@@ -101,7 +114,7 @@
} else {
mEventHandler = null;
}
- nativeInit(texName, new WeakReference<SurfaceTexture>(this));
+ nativeInit(texName, new WeakReference<SurfaceTexture>(this), allowSynchronousMode);
}
/**
@@ -209,12 +222,13 @@
}
}
- private native void nativeInit(int texName, Object weakSelf);
+ private native void nativeInit(int texName, Object weakSelf, boolean allowSynchronousMode);
private native void nativeFinalize();
private native void nativeGetTransformMatrix(float[] mtx);
private native long nativeGetTimestamp();
private native void nativeSetDefaultBufferSize(int width, int height);
private native void nativeUpdateTexImage();
+ private native int nativeGetQueuedCount();
/*
* We use a class initializer to allow the native code to cache some
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index a4734ff..7e03e1c 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -405,8 +405,11 @@
@Override
public void setAlpha(int alpha) {
- mBitmapState.mPaint.setAlpha(alpha);
- invalidateSelf();
+ int oldAlpha = mBitmapState.mPaint.getAlpha();
+ if (alpha != oldAlpha) {
+ mBitmapState.mPaint.setAlpha(alpha);
+ invalidateSelf();
+ }
}
@Override
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a9414e8..b0f7fd3 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,6 +167,7 @@
}
if (mCurrDrawable != null) {
mCurrDrawable.jumpToCurrentState();
+ mCurrDrawable.setAlpha(mAlpha);
}
if (mExitAnimationEnd != 0) {
mExitAnimationEnd = 0;
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 9a3ca40..483fa56 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -187,8 +187,20 @@
final int alpha = mAlpha;
final boolean crossFade = mCrossFade;
final ChildDrawable[] array = mLayerState.mChildren;
- Drawable d;
+ if (done) {
+ // the setAlpha() calls below trigger invalidation and redraw. If we're done, just draw
+ // the appropriate drawable[s] and return
+ if (!crossFade || alpha == 0) {
+ array[0].mDrawable.draw(canvas);
+ }
+ if (alpha == 0xFF) {
+ array[1].mDrawable.draw(canvas);
+ }
+ return;
+ }
+
+ Drawable d;
d = array[0].mDrawable;
if (crossFade) {
d.setAlpha(255 - alpha);
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index a63abb9..e900584 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -79,7 +79,7 @@
/**
* GRAPHICS_TEXTURE The allcation will be used as a texture
- * source by one or more graphcics programs.
+ * source by one or more graphics programs.
*
*/
public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
@@ -606,9 +606,9 @@
*/
public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
mRS.nAllocationData2D(getID(), off, 0,
- 0, Type.CubemapFace.POSITVE_X.mID,
+ 0, Type.CubemapFace.POSITIVE_X.mID,
count, 1, data.getID(), dataOff, 0,
- 0, Type.CubemapFace.POSITVE_X.mID);
+ 0, Type.CubemapFace.POSITIVE_X.mID);
}
private void validate2DRange(int xoff, int yoff, int w, int h) {
@@ -675,9 +675,9 @@
mRS.validate();
validate2DRange(xoff, yoff, w, h);
mRS.nAllocationData2D(getID(), xoff, yoff,
- 0, Type.CubemapFace.POSITVE_X.mID,
+ 0, Type.CubemapFace.POSITIVE_X.mID,
w, h, data.getID(), dataXoff, dataYoff,
- 0, Type.CubemapFace.POSITVE_X.mID);
+ 0, Type.CubemapFace.POSITIVE_X.mID);
}
/**
@@ -1048,15 +1048,15 @@
Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
- adapter.setFace(Type.CubemapFace.POSITVE_X);
+ adapter.setFace(Type.CubemapFace.POSITIVE_X);
adapter.copyFrom(xpos);
adapter.setFace(Type.CubemapFace.NEGATIVE_X);
adapter.copyFrom(xneg);
- adapter.setFace(Type.CubemapFace.POSITVE_Y);
+ adapter.setFace(Type.CubemapFace.POSITIVE_Y);
adapter.copyFrom(ypos);
adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
adapter.copyFrom(yneg);
- adapter.setFace(Type.CubemapFace.POSITVE_Z);
+ adapter.setFace(Type.CubemapFace.POSITIVE_Z);
adapter.copyFrom(zpos);
adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
adapter.copyFrom(zneg);
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index 07a1f5d..77dd86a 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -27,23 +27,30 @@
*
**/
public class AllocationAdapter extends Allocation {
+ private boolean mConstrainedLOD;
+ private boolean mConstrainedFace;
+ private boolean mConstrainedY;
+ private boolean mConstrainedZ;
+
private int mSelectedDimX;
private int mSelectedDimY;
+ private int mSelectedDimZ;
private int mSelectedCount;
private Allocation mAlloc;
private int mSelectedLOD = 0;
- private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITVE_X;
+ private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
super(id, rs, null, alloc.mUsage);
- Type t = alloc.getType();
- mSelectedDimX = t.getX();
- mSelectedDimY = t.getY();
- mSelectedCount = t.getCount();
+ mAlloc = alloc;
}
+ int getID() {
+ return mAlloc.getID();
+ }
+
public void copyFrom(BaseObj[] d) {
mRS.validate();
if (d.length != mSelectedCount) {
@@ -54,7 +61,7 @@
for (int ct=0; ct < d.length; ct++) {
i[ct] = d[ct].getID();
}
- subData1D(0, mType.getCount(), i);
+ subData1D(0, mAlloc.mType.getCount(), i);
}
void validateBitmap(Bitmap b) {
@@ -93,7 +100,7 @@
public void subData(int xoff, FieldPacker fp) {
- int eSize = mType.mElement.getSizeBytes();
+ int eSize = mAlloc.mType.mElement.getSizeBytes();
final byte[] data = fp.getData();
int count = data.length / eSize;
@@ -107,7 +114,7 @@
public void subElementData(int xoff, int component_number, FieldPacker fp) {
- if (component_number >= mType.mElement.mElements.length) {
+ if (component_number >= mAlloc.mType.mElement.mElements.length) {
throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
}
if(xoff < 0) {
@@ -115,7 +122,7 @@
}
final byte[] data = fp.getData();
- int eSize = mType.mElement.mElements[component_number].getSizeBytes();
+ int eSize = mAlloc.mType.mElement.mElements[component_number].getSizeBytes();
if (data.length != eSize) {
throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
@@ -133,12 +140,13 @@
if(count < 1) {
throw new RSIllegalArgumentException("Count must be >= 1.");
}
- if((off + count) > mSelectedDimX * mSelectedDimY) {
- throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() +
+ if((off + count) > mSelectedCount) {
+ throw new RSIllegalArgumentException("Overflow, Available count " + mAlloc.mType.getCount() +
", got " + count + " at offset " + off + ".");
}
if((len) < dataSize) {
- throw new RSIllegalArgumentException("Array too small for allocation type.");
+ throw new RSIllegalArgumentException("Array too small for allocation type. len = " +
+ len + ", dataSize = " + dataSize);
}
}
@@ -223,8 +231,51 @@
mRS.nAllocationRead(getID(), d);
}
+ private void initLOD(int lod) {
+ if (lod < 0) {
+ throw new RSIllegalArgumentException("Attempting to set negative lod (" + lod + ").");
+ }
+
+ int tx = mAlloc.mType.getX();
+ int ty = mAlloc.mType.getY();
+ int tz = mAlloc.mType.getZ();
+
+ for (int ct=0; ct < lod; ct++) {
+ if ((tx==1) && (ty == 1) && (tz == 1)) {
+ throw new RSIllegalArgumentException("Attempting to set lod (" + lod + ") out of range.");
+ }
+
+ if (tx > 1) tx >>= 1;
+ if (ty > 1) ty >>= 1;
+ if (tz > 1) tz >>= 1;
+ }
+
+ mSelectedDimX = tx;
+ mSelectedDimY = ty;
+ mSelectedCount = tx;
+ if (ty > 1) {
+ mSelectedCount *= ty;
+ }
+ if (tz > 1) {
+ mSelectedCount *= tz;
+ }
+ }
+
+ /**
+ * Set the active LOD. The LOD must be within the range for the
+ * type being adapted.
+ *
+ * @param lod The LOD to make active.
+ */
public void setLOD(int lod) {
- mSelectedLOD = lod;
+ if (!mAlloc.getType().hasMipmaps()) {
+ throw new RSInvalidStateException("Cannot set LOD when the allocation type does not include mipmaps.");
+ }
+ if (!mConstrainedLOD) {
+ throw new RSInvalidStateException("Cannot set LOD when the adapter includes mipmaps.");
+ }
+
+ initLOD(lod);
}
public void setFace(Type.CubemapFace cf) {
@@ -245,6 +296,11 @@
static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
rs.validate();
AllocationAdapter aa = new AllocationAdapter(0, rs, a);
+ aa.mConstrainedLOD = true;
+ aa.mConstrainedFace = true;
+ aa.mConstrainedY = false;
+ aa.mConstrainedZ = true;
+ aa.initLOD(0);
return aa;
}
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 0c1ad2a..f844331 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -32,8 +32,8 @@
* <p>Complex elements contain a list of sub-elements and names that
* represents a structure of data. The fields can be accessed by name
* from a script or shader. The memory layout is defined and ordered. Data
- * alignment is determinied by the most basic primitive type. i.e. a float4
- * vector will be alligned to sizeof(float) and not sizeof(float4). The
+ * alignment is determined by the most basic primitive type. i.e. a float4
+ * vector will be aligned to sizeof(float) and not sizeof(float4). The
* ordering of elements in memory will be the order in which they were added
* with each component aligned as necessary. No re-ordering will be done.</p>
*
@@ -383,6 +383,41 @@
return rs.mElement_FLOAT_4;
}
+ public static Element F64_2(RenderScript rs) {
+ if(rs.mElement_DOUBLE_2 == null) {
+ rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2);
+ }
+ return rs.mElement_DOUBLE_2;
+ }
+
+ public static Element F64_3(RenderScript rs) {
+ if(rs.mElement_DOUBLE_3 == null) {
+ rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3);
+ }
+ return rs.mElement_DOUBLE_3;
+ }
+
+ public static Element F64_4(RenderScript rs) {
+ if(rs.mElement_DOUBLE_4 == null) {
+ rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4);
+ }
+ return rs.mElement_DOUBLE_4;
+ }
+
+ public static Element U8_2(RenderScript rs) {
+ if(rs.mElement_UCHAR_2 == null) {
+ rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2);
+ }
+ return rs.mElement_UCHAR_2;
+ }
+
+ public static Element U8_3(RenderScript rs) {
+ if(rs.mElement_UCHAR_3 == null) {
+ rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3);
+ }
+ return rs.mElement_UCHAR_3;
+ }
+
public static Element U8_4(RenderScript rs) {
if(rs.mElement_UCHAR_4 == null) {
rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4);
@@ -390,6 +425,153 @@
return rs.mElement_UCHAR_4;
}
+ public static Element I8_2(RenderScript rs) {
+ if(rs.mElement_CHAR_2 == null) {
+ rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2);
+ }
+ return rs.mElement_CHAR_2;
+ }
+
+ public static Element I8_3(RenderScript rs) {
+ if(rs.mElement_CHAR_3 == null) {
+ rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3);
+ }
+ return rs.mElement_CHAR_3;
+ }
+
+ public static Element I8_4(RenderScript rs) {
+ if(rs.mElement_CHAR_4 == null) {
+ rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4);
+ }
+ return rs.mElement_CHAR_4;
+ }
+
+ public static Element U16_2(RenderScript rs) {
+ if(rs.mElement_USHORT_2 == null) {
+ rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2);
+ }
+ return rs.mElement_USHORT_2;
+ }
+
+ public static Element U16_3(RenderScript rs) {
+ if(rs.mElement_USHORT_3 == null) {
+ rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3);
+ }
+ return rs.mElement_USHORT_3;
+ }
+
+ public static Element U16_4(RenderScript rs) {
+ if(rs.mElement_USHORT_4 == null) {
+ rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4);
+ }
+ return rs.mElement_USHORT_4;
+ }
+
+ public static Element I16_2(RenderScript rs) {
+ if(rs.mElement_SHORT_2 == null) {
+ rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2);
+ }
+ return rs.mElement_SHORT_2;
+ }
+
+ public static Element I16_3(RenderScript rs) {
+ if(rs.mElement_SHORT_3 == null) {
+ rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3);
+ }
+ return rs.mElement_SHORT_3;
+ }
+
+ public static Element I16_4(RenderScript rs) {
+ if(rs.mElement_SHORT_4 == null) {
+ rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4);
+ }
+ return rs.mElement_SHORT_4;
+ }
+
+ public static Element U32_2(RenderScript rs) {
+ if(rs.mElement_UINT_2 == null) {
+ rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2);
+ }
+ return rs.mElement_UINT_2;
+ }
+
+ public static Element U32_3(RenderScript rs) {
+ if(rs.mElement_UINT_3 == null) {
+ rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3);
+ }
+ return rs.mElement_UINT_3;
+ }
+
+ public static Element U32_4(RenderScript rs) {
+ if(rs.mElement_UINT_4 == null) {
+ rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4);
+ }
+ return rs.mElement_UINT_4;
+ }
+
+ public static Element I32_2(RenderScript rs) {
+ if(rs.mElement_INT_2 == null) {
+ rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2);
+ }
+ return rs.mElement_INT_2;
+ }
+
+ public static Element I32_3(RenderScript rs) {
+ if(rs.mElement_INT_3 == null) {
+ rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3);
+ }
+ return rs.mElement_INT_3;
+ }
+
+ public static Element I32_4(RenderScript rs) {
+ if(rs.mElement_INT_4 == null) {
+ rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4);
+ }
+ return rs.mElement_INT_4;
+ }
+
+ public static Element U64_2(RenderScript rs) {
+ if(rs.mElement_ULONG_2 == null) {
+ rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2);
+ }
+ return rs.mElement_ULONG_2;
+ }
+
+ public static Element U64_3(RenderScript rs) {
+ if(rs.mElement_ULONG_3 == null) {
+ rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3);
+ }
+ return rs.mElement_ULONG_3;
+ }
+
+ public static Element U64_4(RenderScript rs) {
+ if(rs.mElement_ULONG_4 == null) {
+ rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4);
+ }
+ return rs.mElement_ULONG_4;
+ }
+
+ public static Element I64_2(RenderScript rs) {
+ if(rs.mElement_LONG_2 == null) {
+ rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2);
+ }
+ return rs.mElement_LONG_2;
+ }
+
+ public static Element I64_3(RenderScript rs) {
+ if(rs.mElement_LONG_3 == null) {
+ rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3);
+ }
+ return rs.mElement_LONG_3;
+ }
+
+ public static Element I64_4(RenderScript rs) {
+ if(rs.mElement_LONG_4 == null) {
+ rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4);
+ }
+ return rs.mElement_LONG_4;
+ }
+
public static Element MATRIX_4X4(RenderScript rs) {
if(rs.mElement_MATRIX_4X4 == null) {
rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
@@ -584,6 +766,33 @@
}
/**
+ * Check if the current Element is compatible with another Element.
+ * Primitive Elements are compatible if they share the same underlying
+ * size and type (i.e. U8 is compatible with A_8). User-defined Elements
+ * must be equal in order to be compatible. This requires strict name
+ * equivalence for all sub-Elements (in addition to structural equivalence).
+ *
+ * @param e The Element to check compatibility with.
+ *
+ * @return boolean true if the Elements are compatible, otherwise false.
+ */
+ public boolean isCompatible(Element e) {
+ // Try strict BaseObj equality to start with.
+ if (this.equals(e)) {
+ return true;
+ }
+
+ // Ignore mKind because it is allowed to be different (user vs. pixel).
+ // We also ignore mNormalized because it can be different. The mType
+ // field must be non-null since we require name equivalence for
+ // user-created Elements.
+ return ((mSize == e.mSize) &&
+ (mType != null) &&
+ (mType == e.mType) &&
+ (mVectorSize == e.mVectorSize));
+ }
+
+ /**
* Builder class for producing complex elements with matching field and name
* pairs. The builder starts empty. The order in which elements are added
* is retained for the layout in memory.
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index fac7144..2739a4b8 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -165,6 +165,22 @@
addF32(v.w);
}
+ public void addF64(Double2 v) {
+ addF64(v.x);
+ addF64(v.y);
+ }
+ public void addF64(Double3 v) {
+ addF64(v.x);
+ addF64(v.y);
+ addF64(v.z);
+ }
+ public void addF64(Double4 v) {
+ addF64(v.x);
+ addF64(v.y);
+ addF64(v.z);
+ addF64(v.w);
+ }
+
public void addI8(Byte2 v) {
addI8(v.x);
addI8(v.y);
@@ -261,6 +277,38 @@
addU32(v.w);
}
+ public void addI64(Long2 v) {
+ addI64(v.x);
+ addI64(v.y);
+ }
+ public void addI64(Long3 v) {
+ addI64(v.x);
+ addI64(v.y);
+ addI64(v.z);
+ }
+ public void addI64(Long4 v) {
+ addI64(v.x);
+ addI64(v.y);
+ addI64(v.z);
+ addI64(v.w);
+ }
+
+ public void addU64(Long2 v) {
+ addU64(v.x);
+ addU64(v.y);
+ }
+ public void addU64(Long3 v) {
+ addU64(v.x);
+ addU64(v.y);
+ addU64(v.z);
+ }
+ public void addU64(Long4 v) {
+ addU64(v.x);
+ addU64(v.y);
+ addU64(v.z);
+ addU64(v.w);
+ }
+
public void addMatrix(Matrix4f v) {
for (int i=0; i < v.mMat.length; i++) {
addF32(v.mMat[i]);
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index fa27590..616990a 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -201,12 +201,14 @@
/**
* Accepts one of the following family names as an argument
- * and will attemp to produce the best match with a system font
+ * and will attempt to produce the best match with a system font:
+ *
* "sans-serif" "arial" "helvetica" "tahoma" "verdana"
* "serif" "times" "times new roman" "palatino" "georgia" "baskerville"
* "goudy" "fantasy" "cursive" "ITC Stone Serif"
* "monospace" "courier" "courier new" "monaco"
- * Returns default font if no match could be found
+ *
+ * Returns default font if no match could be found.
*/
static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
String fileName = getFontFileName(familyName, fontStyle);
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java
new file mode 100644
index 0000000..6046ee1
--- /dev/null
+++ b/graphics/java/android/renderscript/RSTextureView.java
@@ -0,0 +1,177 @@
+/*
+ * 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 android.renderscript;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.content.Context;
+import android.graphics.SurfaceTexture;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.TextureView;
+
+/**
+ * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
+ *
+ * @hide
+ */
+public class RSTextureView extends TextureView implements TextureView.SurfaceTextureListener {
+ private RenderScriptGL mRS;
+ private SurfaceTexture mSurfaceTexture;
+
+ /**
+ * Standard View constructor. In order to render something, you
+ * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+ * register a renderer.
+ */
+ public RSTextureView(Context context) {
+ super(context);
+ init();
+ //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+ }
+
+ /**
+ * Standard View constructor. In order to render something, you
+ * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+ * register a renderer.
+ */
+ public RSTextureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ //Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
+ }
+
+ private void init() {
+ setSurfaceTextureListener(this);
+ //android.util.Log.e("rs", "getSurfaceTextureListerner " + getSurfaceTextureListener());
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureAvailable");
+ mSurfaceTexture = surface;
+
+ if (mRS != null) {
+ mRS.setSurfaceTexture(mSurfaceTexture, width, height);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureSizeChanged");
+ mSurfaceTexture = surface;
+
+ if (mRS != null) {
+ mRS.setSurfaceTexture(mSurfaceTexture, width, height);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureDestroyed");
+ mSurfaceTexture = surface;
+
+ if (mRS != null) {
+ mRS.setSurfaceTexture(null, 0, 0);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ //Log.e(RenderScript.LOG_TAG, "onSurfaceTextureUpdated");
+ mSurfaceTexture = surface;
+ }
+
+ /**
+ * Inform the view that the activity is paused. The owner of this view must
+ * call this method when the activity is paused. Calling this method will
+ * pause the rendering thread.
+ * Must not be called before a renderer has been set.
+ */
+ public void pause() {
+ if(mRS != null) {
+ mRS.pause();
+ }
+ }
+
+ /**
+ * Inform the view that the activity is resumed. The owner of this view must
+ * call this method when the activity is resumed. Calling this method will
+ * recreate the OpenGL display and resume the rendering
+ * thread.
+ * Must not be called before a renderer has been set.
+ */
+ public void resume() {
+ if(mRS != null) {
+ mRS.resume();
+ }
+ }
+
+ /**
+ * Create a new RenderScriptGL object and attach it to the
+ * TextureView if present.
+ *
+ *
+ * @param sc The RS surface config to create.
+ *
+ * @return RenderScriptGL The new object created.
+ */
+ public RenderScriptGL createRenderScriptGL(RenderScriptGL.SurfaceConfig sc) {
+ RenderScriptGL rs = new RenderScriptGL(this.getContext(), sc);
+ setRenderScriptGL(rs);
+ if (mSurfaceTexture != null) {
+ mRS.setSurfaceTexture(mSurfaceTexture, getWidth(), getHeight());
+ }
+ return rs;
+ }
+
+ /**
+ * Destroy the RenderScriptGL object associated with this
+ * TextureView.
+ */
+ public void destroyRenderScriptGL() {
+ mRS.destroy();
+ mRS = null;
+ }
+
+ /**
+ * Set a new RenderScriptGL object. This also will attach the
+ * new object to the TextureView if present.
+ *
+ * @param rs The new RS object.
+ */
+ public void setRenderScriptGL(RenderScriptGL rs) {
+ mRS = rs;
+ if (mSurfaceTexture != null) {
+ mRS.setSurfaceTexture(mSurfaceTexture, getWidth(), getHeight());
+ }
+ }
+
+ /**
+ * Returns the previously set RenderScriptGL object.
+ *
+ * @return RenderScriptGL
+ */
+ public RenderScriptGL getRenderScriptGL() {
+ return mRS;
+ }
+}
+
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2110e37..4856ab6 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -22,6 +22,7 @@
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.SurfaceTexture;
import android.os.Process;
import android.util.Log;
import android.view.Surface;
@@ -109,6 +110,11 @@
validate();
rsnContextSetSurface(mContext, w, h, sur);
}
+ native void rsnContextSetSurfaceTexture(int con, int w, int h, SurfaceTexture sur);
+ synchronized void nContextSetSurfaceTexture(int w, int h, SurfaceTexture sur) {
+ validate();
+ rsnContextSetSurfaceTexture(mContext, w, h, sur);
+ }
native void rsnContextSetPriority(int con, int p);
synchronized void nContextSetPriority(int p) {
validate();
@@ -613,8 +619,43 @@
Element mElement_FLOAT_2;
Element mElement_FLOAT_3;
Element mElement_FLOAT_4;
+
+ Element mElement_DOUBLE_2;
+ Element mElement_DOUBLE_3;
+ Element mElement_DOUBLE_4;
+
+ Element mElement_UCHAR_2;
+ Element mElement_UCHAR_3;
Element mElement_UCHAR_4;
+ Element mElement_CHAR_2;
+ Element mElement_CHAR_3;
+ Element mElement_CHAR_4;
+
+ Element mElement_USHORT_2;
+ Element mElement_USHORT_3;
+ Element mElement_USHORT_4;
+
+ Element mElement_SHORT_2;
+ Element mElement_SHORT_3;
+ Element mElement_SHORT_4;
+
+ Element mElement_UINT_2;
+ Element mElement_UINT_3;
+ Element mElement_UINT_4;
+
+ Element mElement_INT_2;
+ Element mElement_INT_3;
+ Element mElement_INT_4;
+
+ Element mElement_ULONG_2;
+ Element mElement_ULONG_3;
+ Element mElement_ULONG_4;
+
+ Element mElement_LONG_2;
+ Element mElement_LONG_3;
+ Element mElement_LONG_4;
+
Element mElement_MATRIX_4X4;
Element mElement_MATRIX_3X3;
Element mElement_MATRIX_2X2;
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 53b6e28..8b14f99 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -22,6 +22,7 @@
import android.graphics.PixelFormat;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.SurfaceTexture;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
@@ -35,7 +36,6 @@
* the screen.
**/
public class RenderScriptGL extends RenderScript {
- private Surface mSurface;
int mWidth;
int mHeight;
@@ -160,7 +160,6 @@
super(ctx);
mSurfaceConfig = new SurfaceConfig(sc);
- mSurface = null;
mWidth = 0;
mHeight = 0;
mDev = nDeviceCreate();
@@ -189,14 +188,31 @@
*/
public void setSurface(SurfaceHolder sur, int w, int h) {
validate();
+ Surface s = null;
if (sur != null) {
- mSurface = sur.getSurface();
- } else {
- mSurface = null;
+ s = sur.getSurface();
}
mWidth = w;
mHeight = h;
- nContextSetSurface(w, h, mSurface);
+ nContextSetSurface(w, h, s);
+ }
+
+ /**
+ * Bind an os surface
+ *
+ * @hide
+ *
+ * @param w
+ * @param h
+ * @param sur
+ */
+ public void setSurfaceTexture(SurfaceTexture sur, int w, int h) {
+ validate();
+ //android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
+
+ mWidth = w;
+ mHeight = h;
+ nContextSetSurfaceTexture(w, h, sur);
}
/**
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index b39d2e4..f88af8b 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -46,12 +46,18 @@
Element mElement;
public enum CubemapFace {
- POSITVE_X (0),
+ POSITIVE_X (0),
NEGATIVE_X (1),
- POSITVE_Y (2),
+ POSITIVE_Y (2),
NEGATIVE_Y (3),
- POSITVE_Z (4),
- NEGATIVE_Z (5);
+ POSITIVE_Z (4),
+ NEGATIVE_Z (5),
+ @Deprecated
+ POSITVE_X (0),
+ @Deprecated
+ POSITVE_Y (2),
+ @Deprecated
+ POSITVE_Z (4);
int mID;
CubemapFace(int id) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 7e53cc4..4a85faf 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * 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.
@@ -43,6 +43,9 @@
#include <RenderScript.h>
#include <RenderScriptEnv.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
//#define LOG_API LOGE
#define LOG_API(...)
@@ -201,6 +204,23 @@
}
static void
+nContextSetSurfaceTexture(JNIEnv *_env, jobject _this, RsContext con, jint width, jint height, jobject sur)
+{
+ LOG_API("nContextSetSurfaceTexture, con(%p), width(%i), height(%i), surface(%p)", con, width, height, (Surface *)sur);
+
+ sp<ANativeWindow> window;
+ sp<SurfaceTexture> st;
+ if (sur == 0) {
+
+ } else {
+ st = SurfaceTexture_getSurfaceTexture(_env, sur);
+ window = new SurfaceTextureClient(st);
+ }
+
+ rsContextSetSurface(con, width, height, window.get());
+}
+
+static void
nContextDestroy(JNIEnv *_env, jobject _this, RsContext con)
{
LOG_API("nContextDestroy, con(%p)", con);
@@ -1197,6 +1217,7 @@
{"rsnContextFinish", "(I)V", (void*)nContextFinish },
{"rsnContextSetPriority", "(II)V", (void*)nContextSetPriority },
{"rsnContextSetSurface", "(IIILandroid/view/Surface;)V", (void*)nContextSetSurface },
+{"rsnContextSetSurfaceTexture", "(IIILandroid/graphics/SurfaceTexture;)V", (void*)nContextSetSurfaceTexture },
{"rsnContextDestroy", "(I)V", (void*)nContextDestroy },
{"rsnContextDump", "(II)V", (void*)nContextDump },
{"rsnContextPause", "(I)V", (void*)nContextPause },
diff --git a/include/android_runtime/android_view_Surface.h b/include/android_runtime/android_view_Surface.h
index 317f1e7..fb0b057 100644
--- a/include/android_runtime/android_view_Surface.h
+++ b/include/android_runtime/android_view_Surface.h
@@ -23,10 +23,15 @@
namespace android {
+class Surface;
+
extern sp<ANativeWindow> android_Surface_getNativeWindow(
JNIEnv* env, jobject clazz);
extern bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj);
+/* Gets the underlying Surface from a Surface Java object. */
+extern sp<Surface> Surface_getSurface(JNIEnv* env, jobject thiz);
+
} // namespace android
#endif // _ANDROID_VIEW_SURFACE_H
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
index 74d2cc7..2d0db00 100644
--- a/include/binder/IMemory.h
+++ b/include/binder/IMemory.h
@@ -43,6 +43,7 @@
virtual void* getBase() const = 0;
virtual size_t getSize() const = 0;
virtual uint32_t getFlags() const = 0;
+ virtual uint32_t getOffset() const = 0;
// these are there just for backward source compatibility
int32_t heapID() const { return getHeapID(); }
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 2f2e31b..bbbda9c 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -27,7 +27,7 @@
// ---------------------------------------------------------------------------
-class MemoryHeapBase : public virtual BnMemoryHeap
+class MemoryHeapBase : public virtual BnMemoryHeap
{
public:
enum {
@@ -38,12 +38,12 @@
NO_CACHING = 0x00000200
};
- /*
+ /*
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
-
+
/*
* maps memory from the given device
*/
@@ -61,9 +61,10 @@
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
const char* getDevice() const;
-
+
/* this closes this heap -- use carefully */
void dispose();
@@ -74,12 +75,12 @@
mDevice = device;
return mDevice ? NO_ERROR : ALREADY_EXISTS;
}
-
+
protected:
MemoryHeapBase();
// init() takes ownership of fd
status_t init(int fd, void *base, int size,
- int flags = 0, const char* device = NULL);
+ int flags = 0, const char* device = NULL);
private:
status_t mapfd(int fd, size_t size, uint32_t offset = 0);
@@ -90,6 +91,7 @@
uint32_t mFlags;
const char* mDevice;
bool mNeedUnmap;
+ uint32_t mOffset;
};
// ---------------------------------------------------------------------------
diff --git a/include/binder/Permission.h b/include/binder/Permission.h
deleted file mode 100644
index 9542d50..0000000
--- a/include/binder/Permission.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BINDER_PERMISSION_H
-#define BINDER_PERMISSION_H
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include <utils/SortedVector.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-/*
- * Permission caches the result of the permission check for the given
- * permission name and the provided uid/pid. It also handles a few
- * known cases efficiently (caller is in the same process or is root).
- * The package manager does something similar but lives in dalvik world
- * and is therefore extremely slow to access.
- */
-
-class Permission
-{
-public:
- Permission(char const* name);
- Permission(const String16& name);
- Permission(const Permission& rhs);
- virtual ~Permission();
-
- bool operator < (const Permission& rhs) const;
-
- // checks the current binder call's caller has access to this permission
- bool checkCalling() const;
-
- // checks the specified pid/uid has access to this permission
- bool check(pid_t pid, uid_t uid) const;
-
-protected:
- virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
-
-private:
- Permission& operator = (const Permission& rhs) const;
- const String16 mPermissionName;
- mutable SortedVector<uid_t> mGranted;
- const pid_t mPid;
- mutable Mutex mLock;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif /* BINDER_PERMISSION_H */
diff --git a/include/binder/PermissionCache.h b/include/binder/PermissionCache.h
new file mode 100644
index 0000000..1171d48
--- /dev/null
+++ b/include/binder/PermissionCache.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BINDER_PERMISSION_H
+#define BINDER_PERMISSION_H
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <utils/String16.h>
+#include <utils/Singleton.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * PermissionCache caches permission checks for a given uid.
+ *
+ * Currently the cache is not updated when there is a permission change,
+ * for instance when an application is uninstalled.
+ *
+ * IMPORTANT: for the reason stated above, only system permissions are safe
+ * to cache. This restriction may be lifted at a later time.
+ *
+ */
+
+class PermissionCache : Singleton<PermissionCache> {
+ struct Entry {
+ String16 name;
+ uid_t uid;
+ bool granted;
+ inline bool operator < (const Entry& e) const {
+ return (uid == e.uid) ? (name < e.name) : (uid < e.uid);
+ }
+ };
+ mutable Mutex mLock;
+ // we pool all the permission names we see, as many permissions checks
+ // will have identical names
+ SortedVector< String16 > mPermissionNamesPool;
+ // this is our cache per say. it stores pooled names.
+ SortedVector< Entry > mCache;
+
+ // free the whole cache, but keep the permission name pool
+ void purge();
+
+ status_t check(bool* granted,
+ const String16& permission, uid_t uid) const;
+
+ void cache(const String16& permission, uid_t uid, bool granted);
+
+public:
+ PermissionCache();
+
+ static bool checkCallingPermission(const String16& permission);
+
+ static bool checkCallingPermission(const String16& permission,
+ int32_t* outPid, int32_t* outUid);
+
+ static bool checkPermission(const String16& permission,
+ pid_t pid, uid_t uid);
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* BINDER_PERMISSION_H */
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 7106bfa..f701280 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -18,9 +18,11 @@
#define ANDROID_HARDWARE_CAMERA_H
#include <utils/Timers.h>
-#include <camera/ICameraClient.h>
#include <gui/ISurfaceTexture.h>
#include <system/camera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
namespace android {
@@ -70,7 +72,7 @@
static status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo);
static sp<Camera> connect(int cameraId);
- ~Camera();
+ virtual ~Camera();
void init();
status_t reconnect();
@@ -129,8 +131,11 @@
status_t storeMetaDataInBuffers(bool enabled);
void setListener(const sp<CameraListener>& listener);
+ void setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
void setPreviewCallbackFlags(int preview_callback_flag);
+ sp<ICameraRecordingProxy> getRecordingProxy();
+
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
@@ -138,6 +143,20 @@
sp<ICamera> remote();
+ class RecordingProxy : public BnCameraRecordingProxy
+ {
+ public:
+ RecordingProxy(const sp<Camera>& camera);
+
+ // ICameraRecordingProxy interface
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
+ virtual void stopRecording();
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+ private:
+ sp<Camera> mCamera;
+ };
+
private:
Camera();
Camera(const Camera&);
@@ -162,12 +181,12 @@
status_t mStatus;
sp<CameraListener> mListener;
+ sp<ICameraRecordingProxyListener> mRecordingProxyListener;
friend class DeathNotifier;
static Mutex mLock;
static sp<ICameraService> mCameraService;
-
};
}; // namespace android
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
new file mode 100644
index 0000000..2aac284
--- /dev/null
+++ b/include/camera/ICameraRecordingProxy.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ICameraRecordingProxyListener;
+class IMemory;
+class Parcel;
+
+/*
+ * The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to
+ * allow applications using the camera during recording.
+ *
+ * Camera service allows only one client at a time. Since camcorder application
+ * needs to own the camera to do things like zoom, the media recorder cannot
+ * access the camera directly during recording. So ICameraRecordingProxy is a
+ * proxy of ICamera, which allows the media recorder to start/stop the recording
+ * and release recording frames. ICameraRecordingProxyListener is an interface
+ * that allows the recorder to receive video frames during recording.
+ *
+ * ICameraRecordingProxy
+ * startRecording()
+ * stopRecording()
+ * releaseRecordingFrame()
+ *
+ * ICameraRecordingProxyListener
+ * dataCallbackTimestamp()
+
+ * The camcorder app opens the camera and starts the preview. The app passes
+ * ICamera and ICameraRecordingProxy to the media recorder by
+ * MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in
+ * MediaRecorder::start(). After setup, the recorder disconnects from camera
+ * service. The recorder calls ICameraRecordingProxy::startRecording() and
+ * passes a ICameraRecordingProxyListener to the app. The app connects back to
+ * camera service and starts the recording. The app owns the camera and can do
+ * things like zoom. The media recorder receives the video frames from the
+ * listener and releases them by ICameraRecordingProxy::releaseRecordingFrame.
+ * The recorder calls ICameraRecordingProxy::stopRecording() to stop the
+ * recording.
+ *
+ * The call sequences are as follows:
+ * 1. The app: Camera.unlock().
+ * 2. The app: MediaRecorder.setCamera().
+ * 3. Start recording
+ * (1) The app: MediaRecorder.start().
+ * (2) The recorder: ICamera.unlock() and ICamera.disconnect().
+ * (3) The recorder: ICameraRecordingProxy.startRecording().
+ * (4) The app: ICamera.reconnect().
+ * (5) The app: ICamera.startRecording().
+ * 4. During recording
+ * (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp()
+ * (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame().
+ * 5. Stop recording
+ * (1) The app: MediaRecorder.stop()
+ * (2) The recorder: ICameraRecordingProxy.stopRecording().
+ * (3) The app: ICamera.stopRecording().
+ */
+
+class ICameraRecordingProxy: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxy);
+
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
+ virtual void stopRecording() = 0;
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxy: public BnInterface<ICameraRecordingProxy>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
new file mode 100644
index 0000000..b6c0624
--- /dev/null
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+
+#include <binder/IInterface.h>
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Parcel;
+class IMemory;
+
+class ICameraRecordingProxyListener: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxyListener);
+
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+ const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxyListener: public BnInterface<ICameraRecordingProxyListener>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 9294df6..e36360c 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -46,17 +46,20 @@
enum { NUM_BUFFER_SLOTS = 32 };
struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called from queueBuffer() is the FIFO is
- // empty. You can use SurfaceTexture::getQueuedCount() to
- // figure out if there are more frames waiting.
- // This is called without any lock held can be called concurrently by
- // multiple threads.
+ // onFrameAvailable() is called from queueBuffer() each time an
+ // additional frame becomes available for consumption. This means that
+ // frames that are queued while in asynchronous mode only trigger the
+ // callback if no previous frames are pending. Frames queued while in
+ // synchronous mode always trigger the callback.
+ //
+ // This is called without any lock held and can be called concurrently
+ // by multiple threads.
virtual void onFrameAvailable() = 0;
};
// tex indicates the name OpenGL texture to which images are to be streamed.
// This texture name cannot be changed once the SurfaceTexture is created.
- SurfaceTexture(GLuint tex);
+ SurfaceTexture(GLuint tex, bool allowSynchronousMode = true);
virtual ~SurfaceTexture();
@@ -101,11 +104,6 @@
// target texture belongs is bound to the calling thread.
status_t updateTexImage();
- // getqueuedCount returns the number of queued frames waiting in the
- // FIFO. In asynchronous mode, this always returns 0 or 1 since
- // frames are not accumulating in the FIFO.
- size_t getQueuedCount() const;
-
// setBufferCountServer set the buffer count. If the client has requested
// a buffer count using setBufferCount, the server-buffer count will
// take effect once the client sets the count back to zero.
@@ -141,7 +139,7 @@
// setFrameAvailableListener sets the listener object that will be notified
// when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+ void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
// getAllocator retrieves the binder object that must be referenced as long
// as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
@@ -345,7 +343,7 @@
uint32_t mNextTransform;
// mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
+ // be bound when updateTexImage is called. It is set at construction time
// changed with a call to setTexName.
const GLuint mTexName;
@@ -361,6 +359,9 @@
// mSynchronousMode whether we're in synchronous mode or not
bool mSynchronousMode;
+ // mAllowSynchronousMode whether we allow synchronous mode or not
+ const bool mAllowSynchronousMode;
+
// mDequeueCondition condition used for dequeueBuffer in synchronous mode
mutable Condition mDequeueCondition;
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index e7c6e24..6ce44fc 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -80,6 +80,7 @@
int setUsage(uint32_t reqUsage);
void freeAllBuffers();
+ int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
int getConnectedApi() const;
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 28be7c1..a73267d 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,6 +24,7 @@
class Surface;
class ICamera;
+class ICameraRecordingProxy;
class IMediaRecorderClient;
class IMediaRecorder: public IInterface
@@ -31,28 +32,29 @@
public:
DECLARE_META_INTERFACE(MediaRecorder);
- virtual status_t setCamera(const sp<ICamera>& camera) = 0;
- virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
- virtual status_t setVideoSource(int vs) = 0;
- virtual status_t setAudioSource(int as) = 0;
- virtual status_t setOutputFormat(int of) = 0;
- virtual status_t setVideoEncoder(int ve) = 0;
- virtual status_t setAudioEncoder(int ae) = 0;
- virtual status_t setOutputFile(const char* path) = 0;
- virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setOutputFileAuxiliary(int fd) = 0;
- virtual status_t setVideoSize(int width, int height) = 0;
- virtual status_t setVideoFrameRate(int frames_per_second) = 0;
- virtual status_t setParameters(const String8& params) = 0;
- virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
- virtual status_t prepare() = 0;
- virtual status_t getMaxAmplitude(int* max) = 0;
- virtual status_t start() = 0;
- virtual status_t stop() = 0;
- virtual status_t reset() = 0;
- virtual status_t init() = 0;
- virtual status_t close() = 0;
- virtual status_t release() = 0;
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+ virtual status_t setVideoSource(int vs) = 0;
+ virtual status_t setAudioSource(int as) = 0;
+ virtual status_t setOutputFormat(int of) = 0;
+ virtual status_t setVideoEncoder(int ve) = 0;
+ virtual status_t setAudioEncoder(int ae) = 0;
+ virtual status_t setOutputFile(const char* path) = 0;
+ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setOutputFileAuxiliary(int fd) = 0;
+ virtual status_t setVideoSize(int width, int height) = 0;
+ virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+ virtual status_t setParameters(const String8& params) = 0;
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t prepare() = 0;
+ virtual status_t getMaxAmplitude(int* max) = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t reset() = 0;
+ virtual status_t init() = 0;
+ virtual status_t close() = 0;
+ virtual status_t release() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 7e22a24..1c08969 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -24,6 +24,7 @@
namespace android {
+class ICameraRecordingProxy;
class Surface;
struct MediaRecorderBase {
@@ -38,7 +39,8 @@
virtual status_t setVideoEncoder(video_encoder ve) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
- virtual status_t setCamera(const sp<ICamera>& camera) = 0;
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
virtual status_t setOutputFile(const char *path) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
index 9c915ce..07567eb 100644
--- a/include/media/Metadata.h
+++ b/include/media/Metadata.h
@@ -51,47 +51,46 @@
static const Type kAny = 0;
- // Keep in sync with android/media/Metadata.java
- static const Type kTitle = 1; // String
- static const Type kComment = 2; // String
- static const Type kCopyright = 3; // String
- static const Type kAlbum = 4; // String
- static const Type kArtist = 5; // String
- static const Type kAuthor = 6; // String
- static const Type kComposer = 7; // String
- static const Type kGenre = 8; // String
- static const Type kDate = 9; // Date
- static const Type kDuration = 10; // Integer(millisec)
- static const Type kCdTrackNum = 11; // Integer 1-based
- static const Type kCdTrackMax = 12; // Integer
- static const Type kRating = 13; // String
- static const Type kAlbumArt = 14; // byte[]
- static const Type kVideoFrame = 15; // Bitmap
- static const Type kCaption = 16; // TimedText
+ // Playback capabilities.
+ static const Type kPauseAvailable = 1; // Boolean
+ static const Type kSeekBackwardAvailable = 2; // Boolean
+ static const Type kSeekForwardAvailable = 3; // Boolean
+ static const Type kSeekAvailable = 4; // Boolean
- static const Type kBitRate = 17; // Integer, Aggregate rate of
+ // Keep in sync with android/media/Metadata.java
+ static const Type kTitle = 5; // String
+ static const Type kComment = 6; // String
+ static const Type kCopyright = 7; // String
+ static const Type kAlbum = 8; // String
+ static const Type kArtist = 9; // String
+ static const Type kAuthor = 10; // String
+ static const Type kComposer = 11; // String
+ static const Type kGenre = 12; // String
+ static const Type kDate = 13; // Date
+ static const Type kDuration = 14; // Integer(millisec)
+ static const Type kCdTrackNum = 15; // Integer 1-based
+ static const Type kCdTrackMax = 16; // Integer
+ static const Type kRating = 17; // String
+ static const Type kAlbumArt = 18; // byte[]
+ static const Type kVideoFrame = 19; // Bitmap
+
+ static const Type kBitRate = 20; // Integer, Aggregate rate of
// all the streams in bps.
- static const Type kAudioBitRate = 18; // Integer, bps
- static const Type kVideoBitRate = 19; // Integer, bps
- static const Type kAudioSampleRate = 20; // Integer, Hz
- static const Type kVideoframeRate = 21; // Integer, Hz
+ static const Type kAudioBitRate = 21; // Integer, bps
+ static const Type kVideoBitRate = 22; // Integer, bps
+ static const Type kAudioSampleRate = 23; // Integer, Hz
+ static const Type kVideoframeRate = 24; // Integer, Hz
// See RFC2046 and RFC4281.
- static const Type kMimeType = 22; // String
- static const Type kAudioCodec = 23; // String
- static const Type kVideoCodec = 24; // String
+ static const Type kMimeType = 25; // String
+ static const Type kAudioCodec = 26; // String
+ static const Type kVideoCodec = 27; // String
- static const Type kVideoHeight = 25; // Integer
- static const Type kVideoWidth = 26; // Integer
- static const Type kNumTracks = 27; // Integer
- static const Type kDrmCrippled = 28; // Boolean
-
- // Playback capabilities.
- static const Type kPauseAvailable = 29; // Boolean
- static const Type kSeekBackwardAvailable = 30; // Boolean
- static const Type kSeekForwardAvailable = 31; // Boolean
- static const Type kSeekAvailable = 32; // Boolean
+ static const Type kVideoHeight = 28; // Integer
+ static const Type kVideoWidth = 29; // Integer
+ static const Type kNumTracks = 30; // Integer
+ static const Type kDrmCrippled = 31; // Boolean
// @param p[inout] The parcel to append the metadata records
// to. The global metadata header should have been set already.
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 36bf34e..af12d3c 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -30,6 +30,7 @@
class Surface;
class IMediaRecorder;
class ICamera;
+class ICameraRecordingProxy;
typedef void (*media_completion_f)(status_t status, void *cookie);
@@ -202,7 +203,7 @@
void died();
status_t initCheck();
- status_t setCamera(const sp<ICamera>& camera);
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
status_t setPreviewSurface(const sp<Surface>& surface);
status_t setVideoSource(int vs);
status_t setAudioSource(int as);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index bb25bae3..80b7c1c 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -21,6 +21,7 @@
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <camera/ICamera.h>
+#include <camera/ICameraRecordingProxyListener.h>
#include <camera/CameraParameters.h>
#include <utils/List.h>
#include <utils/RefBase.h>
@@ -68,6 +69,7 @@
* @return NULL on error.
*/
static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
@@ -111,6 +113,23 @@
virtual void signalBufferReturned(MediaBuffer* buffer);
protected:
+ class ProxyListener: public BnCameraRecordingProxyListener {
+ public:
+ ProxyListener(const sp<CameraSource>& source);
+ virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data);
+
+ private:
+ sp<CameraSource> mSource;
+ };
+
+ // isBinderAlive needs linkToDeath to work.
+ class DeathNotifier: public IBinder::DeathRecipient {
+ public:
+ DeathNotifier() {}
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
enum CameraFlags {
FLAGS_SET_CAMERA = 1L << 0,
FLAGS_HOT_CAMERA = 1L << 1,
@@ -123,6 +142,8 @@
status_t mInitCheck;
sp<Camera> mCamera;
+ sp<ICameraRecordingProxy> mCameraRecordingProxy;
+ sp<DeathNotifier> mDeathNotifier;
sp<Surface> mSurface;
sp<MetaData> mMeta;
@@ -132,7 +153,8 @@
bool mStarted;
int32_t mNumFramesEncoded;
- CameraSource(const sp<ICamera>& camera, int32_t cameraId,
+ CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
Size videoSize, int32_t frameRate,
const sp<Surface>& surface,
bool storeMetaDataInVideoBuffers);
@@ -172,10 +194,12 @@
void releaseOneRecordingFrame(const sp<IMemory>& frame);
- status_t init(const sp<ICamera>& camera, int32_t cameraId,
- Size videoSize, int32_t frameRate,
- bool storeMetaDataInVideoBuffers);
- status_t isCameraAvailable(const sp<ICamera>& camera, int32_t cameraId);
+ status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId, Size videoSize, int32_t frameRate,
+ bool storeMetaDataInVideoBuffers);
+ status_t isCameraAvailable(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId);
status_t isCameraColorFormatSupported(const CameraParameters& params);
status_t configureCamera(CameraParameters* params,
int32_t width, int32_t height,
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 0e5d534..f07ebba 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -33,6 +33,7 @@
public:
static CameraSourceTimeLapse *CreateFromCamera(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
@@ -132,6 +133,7 @@
CameraSourceTimeLapse(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 2ae8a5b..85ba920 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -76,6 +76,9 @@
status_t convertYUV420SemiPlanar(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertTIYUV420PackedSemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst);
+
ColorConverter(const ColorConverter &);
ColorConverter &operator=(const ColorConverter &);
};
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
index f2c6505..e4c1c49 100644
--- a/include/media/stagefright/MPEG2TSWriter.h
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -31,6 +31,10 @@
MPEG2TSWriter(int fd);
MPEG2TSWriter(const char *filename);
+ MPEG2TSWriter(
+ void *cookie,
+ ssize_t (*write)(void *cookie, const void *data, size_t size));
+
virtual status_t addSource(const sp<MediaSource> &source);
virtual status_t start(MetaData *param = NULL);
virtual status_t stop();
@@ -51,6 +55,10 @@
struct SourceInfo;
FILE *mFile;
+
+ void *mWriteCookie;
+ ssize_t (*mWriteFunc)(void *cookie, const void *data, size_t size);
+
sp<ALooper> mLooper;
sp<AHandlerReflector<MPEG2TSWriter> > mReflector;
@@ -69,6 +77,8 @@
void writeProgramMap();
void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
+ ssize_t internalWrite(const void *data, size_t size);
+
DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
};
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index deade5e..99b72ad 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -118,6 +118,9 @@
// The language code for this media
kKeyMediaLanguage = 'lang', // cstring
+
+ // To store the timed text format data
+ kKeyTextFormatData = 'text', // raw data
};
enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 589cefd..92331a1 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -79,6 +79,13 @@
// from MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer);
+ // for use by ACodec
+ static void findMatchingCodecs(
+ const char *mime,
+ bool createEncoder, const char *matchComponentName,
+ uint32_t flags,
+ Vector<String8> *matchingCodecs);
+
protected:
virtual ~OMXCodec();
@@ -311,12 +318,6 @@
static uint32_t getComponentQuirks(
const char *componentName, bool isEncoder);
- static void findMatchingCodecs(
- const char *mime,
- bool createEncoder, const char *matchComponentName,
- uint32_t flags,
- Vector<String8> *matchingCodecs);
-
void restorePatchedDataPointer(BufferInfo *info);
status_t applyRotation();
diff --git a/include/media/stagefright/openmax/OMX_IVCommon.h b/include/media/stagefright/openmax/OMX_IVCommon.h
index 12b4f93..7ed072b 100644
--- a/include/media/stagefright/openmax/OMX_IVCommon.h
+++ b/include/media/stagefright/openmax/OMX_IVCommon.h
@@ -149,6 +149,7 @@
OMX_COLOR_Format24BitABGR6666,
OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+ OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
OMX_COLOR_FormatMax = 0x7FFFFFFF
} OMX_COLOR_FORMATTYPE;
diff --git a/include/pim/EventRecurrence.h b/include/pim/EventRecurrence.h
deleted file mode 100644
index 1ceda41..0000000
--- a/include/pim/EventRecurrence.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _PIM_EVENT_RECURRENCE_H
-#define _PIM_EVENT_RECURRENCE_H
-
-#include <utils/String16.h>
-
-namespace android {
-
-struct EventRecurrence
-{
-public:
- EventRecurrence();
- ~EventRecurrence();
-
- status_t parse(const String16&);
-
-
- enum freq_t {
- SECONDLY = 1,
- MINUTELY = 2,
- HOURLY = 3,
- DAILY = 4,
- WEEKLY = 5,
- MONTHLY = 6,
- YEARLY = 7
- };
-
- enum {
- SU = 0x00010000,
- MO = 0x00020000,
- TU = 0x00040000,
- WE = 0x00080000,
- TH = 0x00100000,
- FR = 0x00200000,
- SA = 0x00400000
- };
-
- freq_t freq;
- String16 until;
- int count;
- int interval;
- int* bysecond;
- int bysecondCount;
- int* byminute;
- int byminuteCount;
- int* byhour;
- int byhourCount;
- int* byday;
- int* bydayNum;
- int bydayCount;
- int* bymonthday;
- int bymonthdayCount;
- int* byyearday;
- int byyeardayCount;
- int* byweekno;
- int byweeknoCount;
- int* bymonth;
- int bymonthCount;
- int* bysetpos;
- int bysetposCount;
- int wkst;
-};
-
-}; // namespace android
-
-#endif // _PIM_EVENT_RECURRENCE_H
diff --git a/include/private/surfaceflinger/LayerState.h b/include/private/surfaceflinger/LayerState.h
index d7fe572e..d2fed41 100644
--- a/include/private/surfaceflinger/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -29,6 +29,7 @@
namespace android {
class Parcel;
+class ISurfaceComposerClient;
struct layer_state_t {
@@ -68,6 +69,13 @@
Region transparentRegion;
};
+struct ComposerState {
+ sp<ISurfaceComposerClient> client;
+ layer_state_t state;
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+};
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 03fd01b..dba98a3 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -34,6 +34,7 @@
// ----------------------------------------------------------------------------
class IMemoryHeap;
+class ComposerState;
class ISurfaceComposer : public IInterface
{
@@ -105,8 +106,7 @@
virtual sp<IMemoryHeap> getCblk() const = 0;
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
- virtual void openGlobalTransaction() = 0;
- virtual void closeGlobalTransaction() = 0;
+ virtual void setTransactionState(const Vector<ComposerState>& state) = 0;
/* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
@@ -149,8 +149,7 @@
CREATE_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
GET_CBLK,
- OPEN_GLOBAL_TRANSACTION,
- CLOSE_GLOBAL_TRANSACTION,
+ SET_TRANSACTION_STATE,
SET_ORIENTATION,
FREEZE_DISPLAY,
UNFREEZE_DISPLAY,
diff --git a/include/surfaceflinger/ISurfaceComposerClient.h b/include/surfaceflinger/ISurfaceComposerClient.h
index 2e75a0e..6e9a654 100644
--- a/include/surfaceflinger/ISurfaceComposerClient.h
+++ b/include/surfaceflinger/ISurfaceComposerClient.h
@@ -37,8 +37,6 @@
// ----------------------------------------------------------------------------
-class layer_state_t;
-
class ISurfaceComposerClient : public IInterface
{
public:
@@ -69,11 +67,6 @@
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t destroySurface(SurfaceID sid) = 0;
-
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t setState(int32_t count, const layer_state_t* states) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 8845dc9..dc2a845 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -40,6 +40,7 @@
class GraphicBuffer;
class GraphicBufferMapper;
class IOMX;
+class ISurfaceTexture;
class Rect;
class Surface;
class SurfaceComposerClient;
@@ -154,6 +155,7 @@
bool isValid();
uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
+ sp<ISurfaceTexture> getSurfaceTexture();
// the lock/unlock APIs must be used from the same thread
status_t lock(SurfaceInfo* info, bool blocking = true);
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index 140b9f8..7fbbfb24 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -37,10 +37,12 @@
// ---------------------------------------------------------------------------
class DisplayInfo;
+class Composer;
class IMemoryHeap;
class ISurfaceComposer;
class Region;
class surface_flinger_cblk_t;
+struct layer_state_t;
// ---------------------------------------------------------------------------
@@ -59,8 +61,11 @@
// ---------------------------------------------------------------------------
+class Composer;
+
class SurfaceComposerClient : public RefBase
{
+ friend class Composer;
public:
SurfaceComposerClient();
virtual ~SurfaceComposerClient();
@@ -101,13 +106,7 @@
// All composer parameters must be changed within a transaction
// several surfaces can be updated in one transaction, all changes are
// committed at once when the transaction is closed.
- // CloseTransaction() usually requires an IPC with the server.
-
- //! Open a composer transaction
- status_t openTransaction();
-
- //! commit the transaction
- status_t closeTransaction();
+ // closeGlobalTransaction() usually requires an IPC with the server.
//! Open a composer transaction on all active SurfaceComposerClients.
static void openGlobalTransaction();
@@ -152,19 +151,12 @@
private:
virtual void onFirstRef();
- inline layer_state_t* get_state_l(SurfaceID id);
- layer_state_t* lockLayerState(SurfaceID id);
- inline void unlockLayerState();
+ Composer& getComposer();
- mutable Mutex mLock;
- SortedVector<layer_state_t> mStates;
- int32_t mTransactionOpen;
- layer_state_t* mPrebuiltLayerState;
-
- // these don't need to be protected because they never change
- // after assignment
+ mutable Mutex mLock;
status_t mStatus;
sp<ISurfaceComposerClient> mClient;
+ Composer& mComposer;
};
// ---------------------------------------------------------------------------
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again). Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+ int64_t a_zero;
+ int64_t b_zero;
+ int32_t a_to_b_numer;
+ uint32_t a_to_b_denom;
+
+ // Transform from A->B
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+ // Transform from B->A
+ // Returns true on success, or false in the case of a singularity or an
+ // overflow.
+ bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+ // Helpers which will reduce the fraction N/D using Euclid's method.
+ template <class T> static void reduce(T* N, T* D);
+ static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 8beec57..0e98aeb 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -32,6 +32,8 @@
template <class TYPE>
class SortedVector : private SortedVectorImpl
{
+ friend class Vector<TYPE>;
+
public:
typedef TYPE value_type;
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index f1e87e6..b908e2a 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -29,6 +29,9 @@
namespace android {
+template <typename TYPE>
+class SortedVector;
+
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
@@ -47,13 +50,17 @@
Vector();
Vector(const Vector<TYPE>& rhs);
+ explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
- /*
+ const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+
+ /*
* empty the vector
*/
@@ -215,6 +222,11 @@
}
template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+ : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
Vector<TYPE>::~Vector() {
finish_vector();
}
@@ -227,6 +239,18 @@
template<class TYPE> inline
const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+ VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+ return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
VectorImpl::operator = (rhs);
return *this;
}
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index fd6c22c..f75208d 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -60,16 +60,17 @@
public static final String WIFI = "WIFI_";
/** Data type for public keys. */
- public static final String PUBLIC_KEY = "KEY";
+ public static final String EXTRA_PUBLIC_KEY = "KEY";
/** Data type for private keys. */
- public static final String PRIVATE_KEY = "PKEY";
+ public static final String EXTRA_PRIVATE_KEY = "PKEY";
- /** Data type for certificates. */
- public static final String CERTIFICATE = "CERT";
-
- /** Data type for PKCS12. */
- public static final String PKCS12 = "PKCS12";
+ // historically used by Android
+ public static final String EXTENSION_CRT = ".crt";
+ public static final String EXTENSION_P12 = ".p12";
+ // commonly used on Windows
+ public static final String EXTENSION_CER = ".cer";
+ public static final String EXTENSION_PFX = ".pfx";
/**
* Convert objects to a PEM format, which is used for
@@ -123,18 +124,20 @@
}
}
- private Intent createInstallIntent() {
- Intent intent = new Intent(INSTALL_ACTION);
- intent.setClassName("com.android.certinstaller",
- "com.android.certinstaller.CertInstallerMain");
- return intent;
+ public void install(Context context) {
+ try {
+ Intent intent = KeyChain.createInstallIntent();
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, e.toString());
+ }
}
public void install(Context context, KeyPair pair) {
try {
- Intent intent = createInstallIntent();
- intent.putExtra(PRIVATE_KEY, pair.getPrivate().getEncoded());
- intent.putExtra(PUBLIC_KEY, pair.getPublic().getEncoded());
+ Intent intent = KeyChain.createInstallIntent();
+ intent.putExtra(EXTRA_PRIVATE_KEY, pair.getPrivate().getEncoded());
+ intent.putExtra(EXTRA_PUBLIC_KEY, pair.getPublic().getEncoded());
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w(LOGTAG, e.toString());
@@ -143,7 +146,7 @@
public void install(Context context, String type, byte[] value) {
try {
- Intent intent = createInstallIntent();
+ Intent intent = KeyChain.createInstallIntent();
intent.putExtra(type, value);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 2763e46..23ffd59 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -30,5 +30,6 @@
void installCaCertificate(in byte[] caCertificate);
// APIs used by Settings
+ boolean deleteCaCertificate(String alias);
boolean reset();
}
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 4f1596d..b567207 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -22,6 +22,7 @@
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -88,11 +89,117 @@
public static final String ACCOUNT_TYPE = "com.android.keychain";
/**
+ * Action to bring up the KeyChainActivity
+ */
+ private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";
+
+ /**
+ * Extra for use with {@link #ACTION_CHOOSER}
* @hide Also used by KeyChainActivity implementation
*/
public static final String EXTRA_RESPONSE = "response";
/**
+ * Extra for use with {@link #ACTION_CHOOSER}
+ * @hide Also used by KeyChainActivity implementation
+ */
+ public static final String EXTRA_HOST = "host";
+
+ /**
+ * Extra for use with {@link #ACTION_CHOOSER}
+ * @hide Also used by KeyChainActivity implementation
+ */
+ public static final String EXTRA_PORT = "port";
+
+ /**
+ * Extra for use with {@link #ACTION_CHOOSER}
+ * @hide Also used by KeyChainActivity implementation
+ */
+ public static final String EXTRA_ALIAS = "alias";
+
+ /**
+ * Extra for use with {@link #ACTION_CHOOSER}
+ * @hide Also used by KeyChainActivity implementation
+ */
+ public static final String EXTRA_SENDER = "sender";
+
+ /**
+ * Action to bring up the CertInstaller
+ */
+ private static final String ACTION_INSTALL = "android.credentials.INSTALL";
+
+ /**
+ * Optional extra to specify a {@code String} credential name on
+ * the {@code Intent} returned by {@link #createInstallIntent}.
+ *
+ * @hide TODO make public
+ */
+ // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY
+ public static final String EXTRA_NAME = "name";
+
+ /**
+ * Optional extra to specify an X.509 certificate to install on
+ * the {@code Intent} returned by {@link #createInstallIntent}.
+ * The extra value should be a PEM or ASN.1 DER encoded {@code
+ * byte[]}. An {@link X509Certificate} can be converted to DER
+ * encoded bytes with {@link X509Certificate#getEncoded}.
+ *
+ * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+ * name for the installed certificate.
+ *
+ * @hide TODO make public
+ */
+ // Compatible with old android.security.Credentials.CERTIFICATE
+ public static final String EXTRA_CERTIFICATE = "CERT";
+
+ /**
+ * Optional extra for use with the {@code Intent} returned by
+ * {@link #createInstallIntent} to specify a PKCS#12 key store to
+ * install. The extra value should be a {@code byte[]}. The bytes
+ * may come from an external source or be generated with {@link
+ * KeyStore#store} on a "PKCS12" instance.
+ *
+ * <p>The user will be prompted for the password to load the key store.
+ *
+ * <p>The key store will be scanned for {@link
+ * java.security.KeyStore.PrivateKeyEntry} entries and both the
+ * private key and associated certificate chain will be installed.
+ *
+ * <p>{@link #EXTRA_NAME} may be used to provide a default alias
+ * name for the installed credentials.
+ *
+ * @hide TODO make public
+ */
+ // Compatible with old android.security.Credentials.PKCS12
+ public static final String EXTRA_PKCS12 = "PKCS12";
+
+ /**
+ * Returns an {@code Intent} that can be used for credential
+ * installation. The intent may be used without any extras, in
+ * which case the user will be able to install credentials from
+ * their own source.
+ *
+ * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link
+ * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509
+ * certificate or a PKCS#12 key store for installation. These
+ * extras may be combined with {@link EXTRA_NAME} to provide a
+ * default alias name for credentials being installed.
+ *
+ * <p>When used with {@link Activity#startActivityForResult},
+ * {@link Activity#RESULT_OK} will be returned if a credential was
+ * successfully installed, otherwise {@link
+ * Activity#RESULT_CANCELED} will be returned.
+ *
+ * @hide TODO make public with createInstallIntent, EXTRA_NAME, EXTRA_CERTIFICATE, EXTRA_PKCS12
+ */
+ public static Intent createInstallIntent() {
+ Intent intent = new Intent(ACTION_INSTALL);
+ intent.setClassName("com.android.certinstaller",
+ "com.android.certinstaller.CertInstallerMain");
+ return intent;
+ }
+
+ /**
* Launches an {@code Activity} for the user to select the alias
* for a private key and certificate pair for authentication. The
* selected alias or null will be returned via the
@@ -106,6 +213,9 @@
* <p>{@code host} and {@code port} may be used to give the user
* more context about the server requesting the credentials.
*
+ * <p>{@code alias} allows the chooser to preselect an existing
+ * alias which will still be subject to user confirmation.
+ *
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#USE_CREDENTIALS}.
*
@@ -123,14 +233,17 @@
* certificate, or null if unavailable.
* @param port The port number of the server requesting the
* certificate, or -1 if unavailable.
+ * @param alias The alias to preselect if available, or null if
+ * unavailable.
*/
public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response,
String[] keyTypes, Principal[] issuers,
- String host, int port) {
+ String host, int port,
+ String alias) {
/*
- * TODO currently keyTypes, issuers, host, and port are
- * unused. They are meant to follow the semantics and purpose
- * of X509KeyManager method arguments.
+ * TODO currently keyTypes, issuers are unused. They are meant
+ * to follow the semantics and purpose of X509KeyManager
+ * method arguments.
*
* keyTypes would allow the list to be filtered and typically
* will be set correctly by the server. In practice today,
@@ -142,11 +255,6 @@
* server. Others will send none. If this is used, if there
* are no matches after applying the constraint, it should be
* ignored.
- *
- * host and port may be shown to the user if available, but it
- * should be clear that they are not validated values, perhaps
- * shown along with requesting application identity to clarify
- * the source of the request.
*/
if (activity == null) {
throw new NullPointerException("activity == null");
@@ -154,8 +262,13 @@
if (response == null) {
throw new NullPointerException("response == null");
}
- Intent intent = new Intent("com.android.keychain.CHOOSER");
+ Intent intent = new Intent(ACTION_CHOOSER);
intent.putExtra(EXTRA_RESPONSE, new AliasResponse(activity, response));
+ intent.putExtra(EXTRA_HOST, host);
+ intent.putExtra(EXTRA_PORT, port);
+ intent.putExtra(EXTRA_ALIAS, alias);
+ // the PendingIntent is used to get calling package name
+ intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
activity.startActivity(intent);
}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 4582aa0..15e253c 100755
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -75,11 +75,21 @@
assertEquals(KeyStore.State.UNLOCKED, mKeyStore.state());
}
+ public void testGet() throws Exception {
+ assertNull(mKeyStore.get(TEST_KEYNAME));
+ mKeyStore.password(TEST_PASSWD);
+ assertNull(mKeyStore.get(TEST_KEYNAME));
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
+ }
+
public void testPut() throws Exception {
+ assertNull(mKeyStore.get(TEST_KEYNAME));
assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
mKeyStore.password(TEST_PASSWD);
assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
+ assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
}
public void testI18n() throws Exception {
@@ -96,7 +106,9 @@
assertTrue(mKeyStore.delete(TEST_KEYNAME));
mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+ assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
assertTrue(mKeyStore.delete(TEST_KEYNAME));
+ assertNull(mKeyStore.get(TEST_KEYNAME));
}
public void testContains() throws Exception {
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index f9d9f25..3a12e96 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,7 +27,7 @@
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
- Permission.cpp \
+ PermissionCache.cpp \
ProcessState.cpp \
Static.cpp
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index bc8c412..1ace8f8 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -42,11 +42,11 @@
public:
HeapCache();
virtual ~HeapCache();
-
+
virtual void binderDied(const wp<IBinder>& who);
- sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
- void free_heap(const sp<IBinder>& binder);
+ sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
+ void free_heap(const sp<IBinder>& binder);
sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
void dump_heaps();
@@ -57,7 +57,7 @@
int32_t count;
};
- void free_heap(const wp<IBinder>& binder);
+ void free_heap(const wp<IBinder>& binder);
Mutex mHeapCacheLock;
KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
@@ -81,11 +81,12 @@
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
private:
friend class IMemory;
friend class HeapCache;
-
+
// for debugging in this module
static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
return gHeapCache->find_heap(binder);
@@ -97,7 +98,7 @@
return gHeapCache->get_heap(binder);
}
static inline void dump_heaps() {
- gHeapCache->dump_heaps();
+ gHeapCache->dump_heaps();
}
void assertMapped() const;
@@ -107,6 +108,7 @@
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
+ mutable uint32_t mOffset;
mutable bool mRealHeap;
mutable Mutex mLock;
};
@@ -123,7 +125,7 @@
BpMemory(const sp<IBinder>& impl);
virtual ~BpMemory();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
-
+
private:
mutable sp<IMemoryHeap> mHeap;
mutable ssize_t mOffset;
@@ -203,7 +205,7 @@
BnMemory::BnMemory() {
}
-BnMemory::~BnMemory() {
+BnMemory::~BnMemory() {
}
status_t BnMemory::onTransact(
@@ -229,7 +231,7 @@
BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
: BpInterface<IMemoryHeap>(impl),
- mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false)
+ mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
{
}
@@ -242,7 +244,7 @@
sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
if (VERBOSE) {
- LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
+ LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
binder.get(), this, mSize, mHeapId);
CallStack stack;
stack.update();
@@ -270,6 +272,7 @@
if (mHeapId == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
+ mOffset = heap->mOffset;
android_atomic_write( dup( heap->mHeapId ), &mHeapId );
}
} else {
@@ -286,13 +289,14 @@
// remote call without mLock held, worse case scenario, we end up
// calling transact() from multiple threads, but that's not a problem,
// only mmap below must be in the critical section.
-
+
Parcel data, reply;
data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
status_t err = remote()->transact(HEAP_ID, data, &reply);
int parcel_fd = reply.readFileDescriptor();
ssize_t size = reply.readInt32();
uint32_t flags = reply.readInt32();
+ uint32_t offset = reply.readInt32();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
asBinder().get(), parcel_fd, size, err, strerror(-err));
@@ -309,7 +313,7 @@
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mRealHeap = true;
- mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
+ mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
asBinder().get(), size, fd, strerror(errno));
@@ -317,6 +321,7 @@
} else {
mSize = size;
mFlags = flags;
+ mOffset = offset;
android_atomic_write(fd, &mHeapId);
}
}
@@ -343,14 +348,19 @@
return mFlags;
}
+uint32_t BpMemoryHeap::getOffset() const {
+ assertMapped();
+ return mOffset;
+}
+
// ---------------------------------------------------------------------------
IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
-BnMemoryHeap::BnMemoryHeap() {
+BnMemoryHeap::BnMemoryHeap() {
}
-BnMemoryHeap::~BnMemoryHeap() {
+BnMemoryHeap::~BnMemoryHeap() {
}
status_t BnMemoryHeap::onTransact(
@@ -362,6 +372,7 @@
reply->writeFileDescriptor(getHeapID());
reply->writeInt32(getSize());
reply->writeInt32(getFlags());
+ reply->writeInt32(getOffset());
return NO_ERROR;
} break;
default:
@@ -383,17 +394,17 @@
void HeapCache::binderDied(const wp<IBinder>& binder)
{
//LOGD("binderDied binder=%p", binder.unsafe_get());
- free_heap(binder);
+ free_heap(binder);
}
-sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
+sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
{
Mutex::Autolock _l(mHeapCacheLock);
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) {
heap_info_t& info = mHeapCache.editValueAt(i);
LOGD_IF(VERBOSE,
- "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
+ "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -415,7 +426,7 @@
free_heap( wp<IBinder>(binder) );
}
-void HeapCache::free_heap(const wp<IBinder>& binder)
+void HeapCache::free_heap(const wp<IBinder>& binder)
{
sp<IMemoryHeap> rel;
{
@@ -426,7 +437,7 @@
int32_t c = android_atomic_dec(&info.count);
if (c == 1) {
LOGD_IF(VERBOSE,
- "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
+ "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.unsafe_get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -450,7 +461,7 @@
return realHeap;
}
-void HeapCache::dump_heaps()
+void HeapCache::dump_heaps()
{
Mutex::Autolock _l(mHeapCacheLock);
int c = mHeapCache.size();
@@ -459,7 +470,7 @@
BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)",
mHeapCache.keyAt(i).unsafe_get(),
- info.heap.get(), info.count,
+ info.heap.get(), info.count,
h->mHeapId, h->mBase, h->mSize);
}
}
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 9f501e2..bf4a73f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -40,15 +40,15 @@
// ---------------------------------------------------------------------------
-MemoryHeapBase::MemoryHeapBase()
+MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
- mDevice(NULL), mNeedUnmap(false)
+ mDevice(NULL), mNeedUnmap(false), mOffset(0)
{
}
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
@@ -65,7 +65,7 @@
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
@@ -84,7 +84,7 @@
MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
@@ -141,6 +141,7 @@
}
mFD = fd;
mSize = size;
+ mOffset = offset;
return NO_ERROR;
}
@@ -183,5 +184,9 @@
return mDevice;
}
+uint32_t MemoryHeapBase::getOffset() const {
+ return mOffset;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/binder/Permission.cpp b/libs/binder/Permission.cpp
deleted file mode 100644
index fd8fe69..0000000
--- a/libs/binder/Permission.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdint.h>
-#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/Permission.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-Permission::Permission(char const* name)
- : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const String16& name)
- : mPermissionName(name), mPid(getpid())
-{
-}
-
-Permission::Permission(const Permission& rhs)
- : mPermissionName(rhs.mPermissionName),
- mGranted(rhs.mGranted),
- mPid(rhs.mPid)
-{
-}
-
-Permission::~Permission()
-{
-}
-
-bool Permission::operator < (const Permission& rhs) const
-{
- return mPermissionName < rhs.mPermissionName;
-}
-
-bool Permission::checkCalling() const
-{
- IPCThreadState* ipcState = IPCThreadState::self();
- pid_t pid = ipcState->getCallingPid();
- uid_t uid = ipcState->getCallingUid();
- return doCheckPermission(pid, uid);
-}
-
-bool Permission::check(pid_t pid, uid_t uid) const
-{
- return doCheckPermission(pid, uid);
-}
-
-bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
-{
- if ((uid == 0) || (pid == mPid)) {
- // root and ourselves is always okay
- return true;
- } else {
- // see if we already granted this permission for this uid
- Mutex::Autolock _l(mLock);
- if (mGranted.indexOf(uid) >= 0)
- return true;
- }
-
- bool granted = checkPermission(mPermissionName, pid, uid);
- if (granted) {
- Mutex::Autolock _l(mLock);
- // no need to check again, the old item will be replaced if it is
- // already there.
- mGranted.add(uid);
- }
- return granted;
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
new file mode 100644
index 0000000..7278187
--- /dev/null
+++ b/libs/binder/PermissionCache.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PermissionCache"
+
+#include <stdint.h>
+#include <utils/Log.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
+
+// ----------------------------------------------------------------------------
+
+PermissionCache::PermissionCache() {
+}
+
+status_t PermissionCache::check(bool* granted,
+ const String16& permission, uid_t uid) const {
+ Mutex::Autolock _l(mLock);
+ Entry e;
+ e.name = permission;
+ e.uid = uid;
+ ssize_t index = mCache.indexOf(e);
+ if (index >= 0) {
+ *granted = mCache.itemAt(index).granted;
+ return NO_ERROR;
+ }
+ return NAME_NOT_FOUND;
+}
+
+void PermissionCache::cache(const String16& permission,
+ uid_t uid, bool granted) {
+ Mutex::Autolock _l(mLock);
+ Entry e;
+ ssize_t index = mPermissionNamesPool.indexOf(permission);
+ if (index > 0) {
+ e.name = mPermissionNamesPool.itemAt(index);
+ } else {
+ mPermissionNamesPool.add(permission);
+ e.name = permission;
+ }
+ // note, we don't need to store the pid, which is not actually used in
+ // permission checks
+ e.uid = uid;
+ e.granted = granted;
+ index = mCache.indexOf(e);
+ if (index < 0) {
+ mCache.add(e);
+ }
+}
+
+void PermissionCache::purge() {
+ Mutex::Autolock _l(mLock);
+ mCache.clear();
+}
+
+bool PermissionCache::checkCallingPermission(const String16& permission) {
+ return PermissionCache::checkCallingPermission(permission, NULL, NULL);
+}
+
+bool PermissionCache::checkCallingPermission(
+ const String16& permission, int32_t* outPid, int32_t* outUid) {
+ IPCThreadState* ipcState = IPCThreadState::self();
+ pid_t pid = ipcState->getCallingPid();
+ uid_t uid = ipcState->getCallingUid();
+ if (outPid) *outPid = pid;
+ if (outUid) *outUid = uid;
+ return PermissionCache::checkPermission(permission, pid, uid);
+}
+
+bool PermissionCache::checkPermission(
+ const String16& permission, pid_t pid, uid_t uid) {
+ if ((uid == 0) || (pid == getpid())) {
+ // root and ourselves is always okay
+ return true;
+ }
+
+ PermissionCache& pc(PermissionCache::getInstance());
+ bool granted = false;
+ if (pc.check(&granted, permission, uid) != NO_ERROR) {
+ nsecs_t t = -systemTime();
+ granted = android::checkPermission(permission, pid, uid);
+ t += systemTime();
+ LOGD("checking %s for uid=%d => %s (%d us)",
+ String8(permission).string(), uid,
+ granted?"granted":"denied", (int)ns2us(t));
+ pc.cache(permission, uid, granted);
+ }
+ return granted;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index b17b3d2..dc00957 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -6,7 +6,9 @@
CameraParameters.cpp \
ICamera.cpp \
ICameraClient.cpp \
- ICameraService.cpp
+ ICameraService.cpp \
+ ICameraRecordingProxy.cpp \
+ ICameraRecordingProxyListener.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 5eb48da..3c00db5 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -19,11 +19,12 @@
#define LOG_TAG "Camera"
#include <utils/Log.h>
#include <utils/threads.h>
-
+#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
#include <camera/Camera.h>
+#include <camera/ICameraRecordingProxyListener.h>
#include <camera/ICameraService.h>
#include <surfaceflinger/Surface.h>
@@ -236,6 +237,10 @@
void Camera::stopRecording()
{
LOGV("stopRecording");
+ {
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener.clear();
+ }
sp <ICamera> c = mCamera;
if (c == 0) return;
c->stopRecording();
@@ -327,6 +332,12 @@
mListener = listener;
}
+void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
+{
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener = listener;
+}
+
void Camera::setPreviewCallbackFlags(int flag)
{
LOGV("setPreviewCallbackFlags");
@@ -364,6 +375,19 @@
// callback from camera service when timestamped frame is ready
void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
{
+ // If recording proxy listener is registered, forward the frame and return.
+ // The other listener (mListener) is ignored because the receiver needs to
+ // call releaseRecordingFrame.
+ sp<ICameraRecordingProxyListener> proxylistener;
+ {
+ Mutex::Autolock _l(mLock);
+ proxylistener = mRecordingProxyListener;
+ }
+ if (proxylistener != NULL) {
+ proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+ return;
+ }
+
sp<CameraListener> listener;
{
Mutex::Autolock _l(mLock);
@@ -389,4 +413,34 @@
LOGW("Camera server died!");
}
+sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
+ LOGV("getProxy");
+ return new RecordingProxy(this);
+}
+
+status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
+{
+ LOGV("RecordingProxy::startRecording");
+ mCamera->setRecordingProxyListener(listener);
+ mCamera->reconnect();
+ return mCamera->startRecording();
+}
+
+void Camera::RecordingProxy::stopRecording()
+{
+ LOGV("RecordingProxy::stopRecording");
+ mCamera->stopRecording();
+}
+
+void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+ LOGV("RecordingProxy::releaseRecordingFrame");
+ mCamera->releaseRecordingFrame(mem);
+}
+
+Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
+{
+ mCamera = camera;
+}
+
}; // namespace android
diff --git a/libs/camera/ICameraRecordingProxy.cpp b/libs/camera/ICameraRecordingProxy.cpp
new file mode 100644
index 0000000..64b6a5c
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxy.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxy"
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
+ STOP_RECORDING,
+ RELEASE_RECORDING_FRAME,
+};
+
+
+class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
+{
+public:
+ BpCameraRecordingProxy(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxy>(impl)
+ {
+ }
+
+ status_t startRecording(const sp<ICameraRecordingProxyListener>& listener)
+ {
+ LOGV("startRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(START_RECORDING, data, &reply);
+ return reply.readInt32();
+ }
+
+ void stopRecording()
+ {
+ LOGV("stopRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ remote()->transact(STOP_RECORDING, data, &reply);
+ }
+
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ LOGV("releaseRecordingFrame");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(mem->asBinder());
+ remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxy::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case START_RECORDING: {
+ LOGV("START_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<ICameraRecordingProxyListener> listener =
+ interface_cast<ICameraRecordingProxyListener>(data.readStrongBinder());
+ reply->writeInt32(startRecording(listener));
+ return NO_ERROR;
+ } break;
+ case STOP_RECORDING: {
+ LOGV("STOP_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ stopRecording();
+ return NO_ERROR;
+ } break;
+ case RELEASE_RECORDING_FRAME: {
+ LOGV("RELEASE_RECORDING_FRAME");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+ releaseRecordingFrame(mem);
+ return NO_ERROR;
+ } break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/camera/ICameraRecordingProxyListener.cpp b/libs/camera/ICameraRecordingProxyListener.cpp
new file mode 100644
index 0000000..f8cece5
--- /dev/null
+++ b/libs/camera/ICameraRecordingProxyListener.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
+{
+public:
+ BpCameraRecordingProxyListener(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxyListener>(impl)
+ {
+ }
+
+ void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+ {
+ LOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxyListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case DATA_CALLBACK_TIMESTAMP: {
+ LOGV("DATA_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+ nsecs_t timestamp = data.readInt64();
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ dataCallbackTimestamp(timestamp, msgType, imageData);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 40450a3..c1156d5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,6 +25,8 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <private/surfaceflinger/LayerState.h>
+
#include <surfaceflinger/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
@@ -74,18 +76,17 @@
return interface_cast<IMemoryHeap>(reply.readStrongBinder());
}
- virtual void openGlobalTransaction()
+ virtual void setTransactionState(const Vector<ComposerState>& state)
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::OPEN_GLOBAL_TRANSACTION, data, &reply);
- }
-
- virtual void closeGlobalTransaction()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CLOSE_GLOBAL_TRANSACTION, data, &reply);
+ Vector<ComposerState>::const_iterator b(state.begin());
+ Vector<ComposerState>::const_iterator e(state.end());
+ data.writeInt32(state.size());
+ for ( ; b != e ; ++b ) {
+ b->write(data);
+ }
+ remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
@@ -218,13 +219,17 @@
sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
reply->writeStrongBinder(b);
} break;
- case OPEN_GLOBAL_TRANSACTION: {
+ case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- openGlobalTransaction();
- } break;
- case CLOSE_GLOBAL_TRANSACTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- closeGlobalTransaction();
+ size_t count = data.readInt32();
+ ComposerState s;
+ Vector<ComposerState> state;
+ state.setCapacity(count);
+ for (size_t i=0 ; i<count ; i++) {
+ s.read(data);
+ state.add(s);
+ }
+ setTransactionState(state);
} break;
case SET_ORIENTATION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 8d83392..bc97cac 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -51,8 +51,7 @@
enum {
CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
- DESTROY_SURFACE,
- SET_STATE
+ DESTROY_SURFACE
};
class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
@@ -92,17 +91,6 @@
remote()->transact(DESTROY_SURFACE, data, &reply);
return reply.readInt32();
}
-
- virtual status_t setState(int32_t count, const layer_state_t* states)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
- data.writeInt32(count);
- for (int i=0 ; i<count ; i++)
- states[i].write(data);
- remote()->transact(SET_STATE, data, &reply);
- return reply.readInt32();
- }
};
IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
@@ -133,17 +121,6 @@
reply->writeInt32( destroySurface( data.readInt32() ) );
return NO_ERROR;
} break;
- case SET_STATE: {
- CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
- int32_t count = data.readInt32();
- layer_state_t* states = new layer_state_t[count];
- for (int i=0 ; i<count ; i++)
- states[i].read(data);
- status_t err = setState(count, states);
- delete [] states;
- reply->writeInt32(err);
- return NO_ERROR;
- } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 01c4c7e..87901e8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -17,6 +17,7 @@
#include <utils/Errors.h>
#include <binder/Parcel.h>
#include <private/surfaceflinger/LayerState.h>
+#include <surfaceflinger/ISurfaceComposerClient.h>
namespace android {
@@ -58,4 +59,14 @@
return NO_ERROR;
}
+status_t ComposerState::write(Parcel& output) const {
+ output.writeStrongBinder(client->asBinder());
+ return state.write(output);
+}
+
+status_t ComposerState::read(const Parcel& input) {
+ client = interface_cast<ISurfaceComposerClient>(input.readStrongBinder());
+ return state.read(input);
+}
+
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4d1d923..9185e1e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -421,6 +421,10 @@
return NO_ERROR;
}
+sp<ISurfaceTexture> Surface::getSurfaceTexture() {
+ return mSurface != NULL ? mSurface->getSurfaceTexture() : NULL;
+}
+
sp<IBinder> Surface::asBinder() const {
return mSurface!=0 ? mSurface->asBinder() : 0;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1678711..8cead80 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -74,75 +74,52 @@
// ---------------------------------------------------------------------------
+// NOTE: this is NOT a member function (it's a friend defined with its
+// declaration).
+static inline
+int compare_type( const ComposerState& lhs, const ComposerState& rhs) {
+ if (lhs.client < rhs.client) return -1;
+ if (lhs.client > rhs.client) return 1;
+ if (lhs.state.surface < rhs.state.surface) return -1;
+ if (lhs.state.surface > rhs.state.surface) return 1;
+ return 0;
+}
+
class Composer : public Singleton<Composer>
{
- Mutex mLock;
- SortedVector< wp<SurfaceComposerClient> > mActiveConnections;
- SortedVector<sp<SurfaceComposerClient> > mOpenTransactions;
-
- Composer() : Singleton<Composer>() {
- }
-
- void addClientImpl(const sp<SurfaceComposerClient>& client) {
- Mutex::Autolock _l(mLock);
- mActiveConnections.add(client);
- }
-
- void removeClientImpl(const sp<SurfaceComposerClient>& client) {
- Mutex::Autolock _l(mLock);
- mActiveConnections.remove(client);
- }
-
- void openGlobalTransactionImpl()
- {
- Mutex::Autolock _l(mLock);
- if (mOpenTransactions.size()) {
- LOGE("openGlobalTransaction() called more than once. skipping.");
- return;
- }
- const size_t N = mActiveConnections.size();
- for (size_t i=0; i<N; i++) {
- sp<SurfaceComposerClient> client(mActiveConnections[i].promote());
- if (client != 0 && mOpenTransactions.indexOf(client) < 0) {
- if (client->openTransaction() == NO_ERROR) {
- mOpenTransactions.add(client);
- } else {
- LOGE("openTransaction on client %p failed", client.get());
- // let it go, it'll fail later when the user
- // tries to do something with the transaction
- }
- }
- }
- }
-
- void closeGlobalTransactionImpl()
- {
- mLock.lock();
- SortedVector< sp<SurfaceComposerClient> > clients(mOpenTransactions);
- mOpenTransactions.clear();
- mLock.unlock();
-
- sp<ISurfaceComposer> sm(getComposerService());
- sm->openGlobalTransaction();
- const size_t N = clients.size();
- for (size_t i=0; i<N; i++) {
- clients[i]->closeTransaction();
- }
- sm->closeGlobalTransaction();
- }
-
friend class Singleton<Composer>;
+ mutable Mutex mLock;
+ SortedVector<ComposerState> mStates;
+
+ Composer() : Singleton<Composer>() { }
+
+ void closeGlobalTransactionImpl();
+
+ layer_state_t* getLayerStateLocked(
+ const sp<SurfaceComposerClient>& client, SurfaceID id);
+
public:
- static void addClient(const sp<SurfaceComposerClient>& client) {
- Composer::getInstance().addClientImpl(client);
- }
- static void removeClient(const sp<SurfaceComposerClient>& client) {
- Composer::getInstance().removeClientImpl(client);
- }
- static void openGlobalTransaction() {
- Composer::getInstance().openGlobalTransactionImpl();
- }
+
+ status_t setPosition(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ int32_t x, int32_t y);
+ status_t setSize(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t w, uint32_t h);
+ status_t setLayer(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ int32_t z);
+ status_t setFlags(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t flags, uint32_t mask);
+ status_t setTransparentRegionHint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ const Region& transparentRegion);
+ status_t setAlpha(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ float alpha);
+ status_t setMatrix(const sp<SurfaceComposerClient>& client, SurfaceID id,
+ float dsdx, float dtdx, float dsdy, float dtdy);
+ status_t setFreezeTint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ uint32_t tint);
+
static void closeGlobalTransaction() {
Composer::getInstance().closeGlobalTransactionImpl();
}
@@ -152,69 +129,306 @@
// ---------------------------------------------------------------------------
-static inline int compare_type( const layer_state_t& lhs,
- const layer_state_t& rhs) {
- if (lhs.surface < rhs.surface) return -1;
- if (lhs.surface > rhs.surface) return 1;
- return 0;
+void Composer::closeGlobalTransactionImpl() {
+ sp<ISurfaceComposer> sm(getComposerService());
+
+ Vector<ComposerState> transaction;
+
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ transaction = mStates;
+ mStates.clear();
+ }
+
+ sm->setTransactionState(transaction);
}
+layer_state_t* Composer::getLayerStateLocked(
+ const sp<SurfaceComposerClient>& client, SurfaceID id) {
+
+ ComposerState s;
+ s.client = client->mClient;
+ s.state.surface = id;
+
+ ssize_t index = mStates.indexOf(s);
+ if (index < 0) {
+ // we don't have it, add an initialized layer_state to our list
+ index = mStates.add(s);
+ }
+
+ ComposerState* const out = mStates.editArray();
+ return &(out[index].state);
+}
+
+status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, int32_t x, int32_t y) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::ePositionChanged;
+ s->x = x;
+ s->y = y;
+ return NO_ERROR;
+}
+
+status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t w, uint32_t h) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eSizeChanged;
+ s->w = w;
+ s->h = h;
+ return NO_ERROR;
+}
+
+status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, int32_t z) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eLayerChanged;
+ s->z = z;
+ return NO_ERROR;
+}
+
+status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t flags,
+ uint32_t mask) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eVisibilityChanged;
+ s->flags &= ~mask;
+ s->flags |= (flags & mask);
+ s->mask |= mask;
+ return NO_ERROR;
+}
+
+status_t Composer::setTransparentRegionHint(
+ const sp<SurfaceComposerClient>& client, SurfaceID id,
+ const Region& transparentRegion) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eTransparentRegionChanged;
+ s->transparentRegion = transparentRegion;
+ return NO_ERROR;
+}
+
+status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, float alpha) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eAlphaChanged;
+ s->alpha = alpha;
+ return NO_ERROR;
+}
+
+status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, float dsdx, float dtdx,
+ float dsdy, float dtdy) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eMatrixChanged;
+ layer_state_t::matrix22_t matrix;
+ matrix.dsdx = dsdx;
+ matrix.dtdx = dtdx;
+ matrix.dsdy = dsdy;
+ matrix.dtdy = dtdy;
+ s->matrix = matrix;
+ return NO_ERROR;
+}
+
+status_t Composer::setFreezeTint(const sp<SurfaceComposerClient>& client,
+ SurfaceID id, uint32_t tint) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s)
+ return BAD_INDEX;
+ s->what |= ISurfaceComposer::eFreezeTintChanged;
+ s->tint = tint;
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
SurfaceComposerClient::SurfaceComposerClient()
- : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT)
+ : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}
-void SurfaceComposerClient::onFirstRef()
-{
+void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sm(getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
- Composer::addClient(this);
- mPrebuiltLayerState = new layer_state_t;
mStatus = NO_ERROR;
}
}
}
-SurfaceComposerClient::~SurfaceComposerClient()
-{
- delete mPrebuiltLayerState;
+SurfaceComposerClient::~SurfaceComposerClient() {
dispose();
}
-status_t SurfaceComposerClient::initCheck() const
-{
+status_t SurfaceComposerClient::initCheck() const {
return mStatus;
}
-sp<IBinder> SurfaceComposerClient::connection() const
-{
+sp<IBinder> SurfaceComposerClient::connection() const {
return (mClient != 0) ? mClient->asBinder() : 0;
}
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
- void* cookie, uint32_t flags)
-{
+ void* cookie, uint32_t flags) {
sp<ISurfaceComposer> sm(getComposerService());
return sm->asBinder()->linkToDeath(recipient, cookie, flags);
}
-void SurfaceComposerClient::dispose()
-{
+void SurfaceComposerClient::dispose() {
// this can be called more than once.
sp<ISurfaceComposerClient> client;
Mutex::Autolock _lm(mLock);
if (mClient != 0) {
- Composer::removeClient(this);
client = mClient; // hold ref while lock is held
mClient.clear();
}
mStatus = NO_INIT;
}
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+ DisplayID display,
+ uint32_t w,
+ uint32_t h,
+ PixelFormat format,
+ uint32_t flags)
+{
+ String8 name;
+ const size_t SIZE = 128;
+ char buffer[SIZE];
+ snprintf(buffer, SIZE, "<pid_%d>", getpid());
+ name.append(buffer);
+
+ return SurfaceComposerClient::createSurface(name, display,
+ w, h, format, flags);
+}
+
+sp<SurfaceControl> SurfaceComposerClient::createSurface(
+ const String8& name,
+ DisplayID display,
+ uint32_t w,
+ uint32_t h,
+ PixelFormat format,
+ uint32_t flags)
+{
+ sp<SurfaceControl> result;
+ if (mStatus == NO_ERROR) {
+ ISurfaceComposerClient::surface_data_t data;
+ sp<ISurface> surface = mClient->createSurface(&data, name,
+ display, w, h, format, flags);
+ if (surface != 0) {
+ result = new SurfaceControl(this, surface, data, w, h, format, flags);
+ }
+ }
+ return result;
+}
+
+status_t SurfaceComposerClient::destroySurface(SurfaceID sid) {
+ if (mStatus != NO_ERROR)
+ return mStatus;
+ status_t err = mClient->destroySurface(sid);
+ return err;
+}
+
+inline Composer& SurfaceComposerClient::getComposer() {
+ return mComposer;
+}
+
+// ----------------------------------------------------------------------------
+
+void SurfaceComposerClient::openGlobalTransaction() {
+ // Currently a no-op
+}
+
+void SurfaceComposerClient::closeGlobalTransaction() {
+ Composer::closeGlobalTransaction();
+}
+
+// ----------------------------------------------------------------------------
+
+status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) {
+ return getComposer().setFreezeTint(this, id, tint);
+}
+
+status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y) {
+ return getComposer().setPosition(this, id, x, y);
+}
+
+status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h) {
+ return getComposer().setSize(this, id, w, h);
+}
+
+status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z) {
+ return getComposer().setLayer(this, id, z);
+}
+
+status_t SurfaceComposerClient::hide(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ ISurfaceComposer::eLayerHidden,
+ ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::show(SurfaceID id, int32_t) {
+ return getComposer().setFlags(this, id,
+ 0,
+ ISurfaceComposer::eLayerHidden);
+}
+
+status_t SurfaceComposerClient::freeze(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ ISurfaceComposer::eLayerFrozen,
+ ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::unfreeze(SurfaceID id) {
+ return getComposer().setFlags(this, id,
+ 0,
+ ISurfaceComposer::eLayerFrozen);
+}
+
+status_t SurfaceComposerClient::setFlags(SurfaceID id, uint32_t flags,
+ uint32_t mask) {
+ return getComposer().setFlags(this, id, flags, mask);
+}
+
+status_t SurfaceComposerClient::setTransparentRegionHint(SurfaceID id,
+ const Region& transparentRegion) {
+ return getComposer().setTransparentRegionHint(this, id, transparentRegion);
+}
+
+status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha) {
+ return getComposer().setAlpha(this, id, alpha);
+}
+
+status_t SurfaceComposerClient::setMatrix(SurfaceID id, float dsdx, float dtdx,
+ float dsdy, float dtdy) {
+ return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
+}
+
+// ----------------------------------------------------------------------------
+
status_t SurfaceComposerClient::getDisplayInfo(
DisplayID dpy, DisplayInfo* info)
{
@@ -273,70 +487,7 @@
return n;
}
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
- DisplayID display,
- uint32_t w,
- uint32_t h,
- PixelFormat format,
- uint32_t flags)
-{
- String8 name;
- const size_t SIZE = 128;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "<pid_%d>", getpid());
- name.append(buffer);
-
- return SurfaceComposerClient::createSurface(name, display,
- w, h, format, flags);
-}
-
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
- const String8& name,
- DisplayID display,
- uint32_t w,
- uint32_t h,
- PixelFormat format,
- uint32_t flags)
-{
- sp<SurfaceControl> result;
- if (mStatus == NO_ERROR) {
- ISurfaceComposerClient::surface_data_t data;
- sp<ISurface> surface = mClient->createSurface(&data, name,
- display, w, h, format, flags);
- if (surface != 0) {
- result = new SurfaceControl(this, surface, data, w, h, format, flags);
- }
- }
- return result;
-}
-
-status_t SurfaceComposerClient::destroySurface(SurfaceID sid)
-{
- if (mStatus != NO_ERROR)
- return mStatus;
-
- // it's okay to destroy a surface while a transaction is open,
- // (transactions really are a client-side concept)
- // however, this indicates probably a misuse of the API or a bug
- // in the client code.
- LOGW_IF(mTransactionOpen,
- "Destroying surface while a transaction is open. "
- "Client %p: destroying surface %d, mTransactionOpen=%d",
- this, sid, mTransactionOpen);
-
- status_t err = mClient->destroySurface(sid);
- return err;
-}
-
-void SurfaceComposerClient::openGlobalTransaction()
-{
- Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction()
-{
- Composer::closeGlobalTransaction();
-}
+// ----------------------------------------------------------------------------
status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
{
@@ -350,199 +501,13 @@
return sm->unfreezeDisplay(dpy, flags);
}
-int SurfaceComposerClient::setOrientation(DisplayID dpy,
+int SurfaceComposerClient::setOrientation(DisplayID dpy,
int orientation, uint32_t flags)
{
sp<ISurfaceComposer> sm(getComposerService());
return sm->setOrientation(dpy, orientation, flags);
}
-status_t SurfaceComposerClient::openTransaction()
-{
- if (mStatus != NO_ERROR)
- return mStatus;
- Mutex::Autolock _l(mLock);
- mTransactionOpen++;
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::closeTransaction()
-{
- if (mStatus != NO_ERROR)
- return mStatus;
-
- Mutex::Autolock _l(mLock);
- if (mTransactionOpen <= 0) {
- LOGE( "closeTransaction (client %p, mTransactionOpen=%d) "
- "called more times than openTransaction()",
- this, mTransactionOpen);
- return INVALID_OPERATION;
- }
-
- if (mTransactionOpen >= 2) {
- mTransactionOpen--;
- return NO_ERROR;
- }
-
- mTransactionOpen = 0;
- const ssize_t count = mStates.size();
- if (count) {
- mClient->setState(count, mStates.array());
- mStates.clear();
- }
- return NO_ERROR;
-}
-
-layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index)
-{
- // API usage error, do nothing.
- if (mTransactionOpen<=0) {
- LOGE("Not in transaction (client=%p, SurfaceID=%d, mTransactionOpen=%d",
- this, int(index), mTransactionOpen);
- return 0;
- }
-
- // use mPrebuiltLayerState just to find out if we already have it
- layer_state_t& dummy(*mPrebuiltLayerState);
- dummy.surface = index;
- ssize_t i = mStates.indexOf(dummy);
- if (i < 0) {
- // we don't have it, add an initialized layer_state to our list
- i = mStates.add(dummy);
- }
- return mStates.editArray() + i;
-}
-
-layer_state_t* SurfaceComposerClient::lockLayerState(SurfaceID id)
-{
- layer_state_t* s;
- mLock.lock();
- s = get_state_l(id);
- if (!s) mLock.unlock();
- return s;
-}
-
-void SurfaceComposerClient::unlockLayerState()
-{
- mLock.unlock();
-}
-
-status_t SurfaceComposerClient::setPosition(SurfaceID id, int32_t x, int32_t y)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::ePositionChanged;
- s->x = x;
- s->y = y;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setSize(SurfaceID id, uint32_t w, uint32_t h)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eSizeChanged;
- s->w = w;
- s->h = h;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setLayer(SurfaceID id, int32_t z)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eLayerChanged;
- s->z = z;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::hide(SurfaceID id)
-{
- return setFlags(id, ISurfaceComposer::eLayerHidden,
- ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(SurfaceID id, int32_t)
-{
- return setFlags(id, 0, ISurfaceComposer::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::freeze(SurfaceID id)
-{
- return setFlags(id, ISurfaceComposer::eLayerFrozen,
- ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::unfreeze(SurfaceID id)
-{
- return setFlags(id, 0, ISurfaceComposer::eLayerFrozen);
-}
-
-status_t SurfaceComposerClient::setFlags(SurfaceID id,
- uint32_t flags, uint32_t mask)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eVisibilityChanged;
- s->flags &= ~mask;
- s->flags |= (flags & mask);
- s->mask |= mask;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(
- SurfaceID id, const Region& transparentRegion)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eTransparentRegionChanged;
- s->transparentRegion = transparentRegion;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setAlpha(SurfaceID id, float alpha)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eAlphaChanged;
- s->alpha = alpha;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setMatrix(
- SurfaceID id,
- float dsdx, float dtdx,
- float dsdy, float dtdy )
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eMatrixChanged;
- layer_state_t::matrix22_t matrix;
- matrix.dsdx = dsdx;
- matrix.dtdx = dtdx;
- matrix.dsdy = dsdy;
- matrix.dtdy = dtdy;
- s->matrix = matrix;
- unlockLayerState();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
-{
- layer_state_t* s = lockLayerState(id);
- if (!s) return BAD_INDEX;
- s->what |= ISurfaceComposer::eFreezeTintChanged;
- s->tint = tint;
- unlockLayerState();
- return NO_ERROR;
-}
-
// ----------------------------------------------------------------------------
ScreenshotClient::ScreenshotClient()
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 3cecdb4..3bf6477 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -78,7 +78,7 @@
static void mtxMul(float out[16], const float a[16], const float b[16]);
-SurfaceTexture::SurfaceTexture(GLuint tex) :
+SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
mDefaultWidth(1),
mDefaultHeight(1),
mPixelFormat(PIXEL_FORMAT_RGBA_8888),
@@ -91,7 +91,8 @@
mCurrentTimestamp(0),
mNextTransform(0),
mTexName(tex),
- mSynchronousMode(false) {
+ mSynchronousMode(false),
+ mAllowSynchronousMode(allowSynchronousMode) {
LOGV("SurfaceTexture::SurfaceTexture");
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -147,6 +148,11 @@
LOGV("SurfaceTexture::setBufferCount");
Mutex::Autolock lock(mMutex);
+ if (bufferCount > NUM_BUFFER_SLOTS) {
+ LOGE("setBufferCount: bufferCount larger than slots available");
+ return BAD_VALUE;
+ }
+
// Error out if the user has dequeued buffers
for (int i=0 ; i<mBufferCount ; i++) {
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
@@ -207,7 +213,7 @@
uint32_t format, uint32_t usage) {
LOGV("SurfaceTexture::dequeueBuffer");
- if ((w && !h) || (!w & h)) {
+ if ((w && !h) || (!w && h)) {
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
return BAD_VALUE;
}
@@ -371,6 +377,9 @@
Mutex::Autolock lock(mMutex);
status_t err = OK;
+ if (!mAllowSynchronousMode && enabled)
+ return err;
+
if (!enabled) {
// going to asynchronous mode, drain the queue
while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
@@ -413,17 +422,22 @@
return -EINVAL;
}
- if (mQueue.empty()) {
- listener = mFrameAvailableListener;
- }
-
if (mSynchronousMode) {
- // in synchronous mode we queue all buffers in a FIFO
+ // In synchronous mode we queue all buffers in a FIFO.
mQueue.push_back(buf);
+
+ // Synchronous mode always signals that an additional frame should
+ // be consumed.
+ listener = mFrameAvailableListener;
} else {
- // in asynchronous mode we only keep the most recent buffer
+ // In asynchronous mode we only keep the most recent buffer.
if (mQueue.empty()) {
mQueue.push_back(buf);
+
+ // Asynchronous mode only signals that a frame should be
+ // consumed if no previous frame was pending. If a frame were
+ // pending then the consumer would have already been notified.
+ listener = mFrameAvailableListener;
} else {
Fifo::iterator front(mQueue.begin());
// buffer currently queued is freed
@@ -479,24 +493,14 @@
status_t SurfaceTexture::updateTexImage() {
LOGV("SurfaceTexture::updateTexImage");
-
Mutex::Autolock lock(mMutex);
- int buf = mCurrentTexture;
+ // In asynchronous mode the list is guaranteed to be one buffer
+ // deep, while in synchronous mode we use the oldest buffer.
if (!mQueue.empty()) {
- // in asynchronous mode the list is guaranteed to be one buffer deep,
- // while in synchronous mode we use the oldest buffer
Fifo::iterator front(mQueue.begin());
- buf = *front;
- mQueue.erase(front);
- if (mQueue.isEmpty()) {
- mDequeueCondition.signal();
- }
- }
+ int buf = *front;
- // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
- // so this check will fail until a buffer gets queued.
- if (mCurrentTexture != buf) {
// Update the GL texture object.
EGLImageKHR image = mSlots[buf].mEglImage;
if (image == EGL_NO_IMAGE_KHR) {
@@ -534,7 +538,7 @@
}
if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- // the current buffer becomes FREE if it was still in the queued
+ // The current buffer becomes FREE if it was still in the queued
// state. If it has already been given to the client
// (synchronous mode), then it stays in DEQUEUED state.
if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
@@ -549,17 +553,17 @@
mCurrentTransform = mSlots[buf].mTransform;
mCurrentTimestamp = mSlots[buf].mTimestamp;
computeCurrentTransformMatrix();
+
+ // Now that we've passed the point at which failures can happen,
+ // it's safe to remove the buffer from the front of the queue.
+ mQueue.erase(front);
mDequeueCondition.signal();
} else {
// We always bind the texture even if we don't update its contents.
glBindTexture(mCurrentTextureTarget, mTexName);
}
- return OK;
-}
-size_t SurfaceTexture::getQueuedCount() const {
- Mutex::Autolock lock(mMutex);
- return mQueue.size();
+ return OK;
}
bool SurfaceTexture::isExternalFormat(uint32_t format)
@@ -700,10 +704,10 @@
}
void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& l) {
+ const sp<FrameAvailableListener>& listener) {
LOGV("SurfaceTexture::setFrameAvailableListener");
Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = l;
+ mFrameAvailableListener = listener;
}
sp<IBinder> SurfaceTexture::getAllocator() {
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 22b0852..b9b2310 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -143,12 +143,40 @@
int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
LOGV("SurfaceTextureClient::cancelBuffer");
Mutex::Autolock lock(mMutex);
+ int i = getSlotFromBufferLocked(buffer);
+ if (i < 0) {
+ return i;
+ }
+ mSurfaceTexture->cancelBuffer(i);
+ return OK;
+}
+
+int SurfaceTextureClient::getSlotFromBufferLocked(
+ android_native_buffer_t* buffer) const {
+ bool dumpedState = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i]->handle == buffer->handle) {
- mSurfaceTexture->cancelBuffer(i);
- return OK;
+ // XXX: Dump the slots whenever we hit a NULL entry while searching for
+ // a buffer.
+ if (mSlots[i] == NULL) {
+ if (!dumpedState) {
+ LOGD("getSlotFromBufferLocked: encountered NULL buffer in slot %d "
+ "looking for buffer %p", i, buffer->handle);
+ for (int j = 0; j < NUM_BUFFER_SLOTS; j++) {
+ if (mSlots[j] == NULL) {
+ LOGD("getSlotFromBufferLocked: %02d: NULL", j);
+ } else {
+ LOGD("getSlotFromBufferLocked: %02d: %p", j, mSlots[j]->handle);
+ }
+ }
+ dumpedState = true;
+ }
+ }
+
+ if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) {
+ return i;
}
}
+ LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
return BAD_VALUE;
}
@@ -169,13 +197,12 @@
} else {
timestamp = mTimestamp;
}
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i]->handle == buffer->handle) {
- return mSurfaceTexture->queueBuffer(i, timestamp);
- }
+ int i = getSlotFromBufferLocked(buffer);
+ if (i < 0) {
+ return i;
}
- LOGE("queueBuffer: unknown buffer queued");
- return BAD_VALUE;
+ mSurfaceTexture->queueBuffer(i, timestamp);
+ return OK;
}
int SurfaceTextureClient::query(int what, int* value) const {
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index a4c5b36..519b40e 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -590,7 +590,7 @@
// This test verifies that the buffer format can be queried immediately after
// it is set.
-TEST_F(SurfaceTextureClientTest, DISABLED_QueryFormatAfterSettingWorks) {
+TEST_F(SurfaceTextureClientTest, QueryFormatAfterSettingWorks) {
sp<ANativeWindow> anw(mSTC);
int fmts[] = {
// RGBA_8888 should not come first, as it's the default
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 50af3bb..c06400e 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -84,10 +84,10 @@
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+ SurfaceComposerClient::openGlobalTransaction();
ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+ SurfaceComposerClient::closeGlobalTransaction();
sp<ANativeWindow> window = mSurfaceControl->getSurface();
mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
@@ -173,11 +173,11 @@
}
virtual EGLint getSurfaceWidth() {
- return 64;
+ return 512;
}
virtual EGLint getSurfaceHeight() {
- return 64;
+ return 512;
}
void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
@@ -419,6 +419,31 @@
ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
}
+ class FrameWaiter : public SurfaceTexture::FrameAvailableListener {
+ public:
+ FrameWaiter():
+ mPendingFrames(0) {
+ }
+
+ void waitForFrame() {
+ Mutex::Autolock lock(mMutex);
+ while (mPendingFrames == 0) {
+ mCondition.wait(mMutex);
+ }
+ mPendingFrames--;
+ }
+
+ virtual void onFrameAvailable() {
+ Mutex::Autolock lock(mMutex);
+ mPendingFrames++;
+ mCondition.signal();
+ }
+
+ int mPendingFrames;
+ Mutex mMutex;
+ Condition mCondition;
+ };
+
sp<SurfaceTexture> mST;
sp<SurfaceTextureClient> mSTC;
sp<ANativeWindow> mANW;
@@ -526,27 +551,24 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, texWidth, texHeight);
drawTexture();
EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255));
EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255));
- EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255));
- EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
+ EXPECT_TRUE(checkPixel(63, 65, 0, 133, 0, 255));
+ EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(22, 44, 247, 70, 255, 255));
- EXPECT_TRUE(checkPixel(45, 52, 209, 32, 235, 255));
- EXPECT_TRUE(checkPixel(52, 51, 100, 255, 73, 255));
+ EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255));
+ EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255));
+ EXPECT_TRUE(checkPixel(52, 51, 98, 255, 73, 255));
EXPECT_TRUE(checkPixel( 7, 31, 155, 0, 118, 255));
- EXPECT_TRUE(checkPixel(31, 9, 148, 71, 110, 255));
+ EXPECT_TRUE(checkPixel(31, 9, 107, 24, 87, 255));
EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255));
EXPECT_TRUE(checkPixel(36, 22, 155, 29, 0, 255));
}
-// XXX: This test is disabled because it it currently broken on all devices to
-// which I have access. Some of the checkPixel calls are not correct because
-// I just copied them from the npot test above and haven't bothered to figure
-// out the correct values.
-TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) {
const int texWidth = 64;
const int texHeight = 64;
@@ -574,20 +596,21 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, texWidth, texHeight);
drawTexture();
- EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255));
+ EXPECT_TRUE(checkPixel( 0, 0, 0, 133, 0, 255));
+ EXPECT_TRUE(checkPixel(63, 0, 255, 127, 255, 255));
EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255));
EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(22, 19, 247, 70, 255, 255));
- EXPECT_TRUE(checkPixel(45, 11, 209, 32, 235, 255));
- EXPECT_TRUE(checkPixel(52, 12, 100, 255, 73, 255));
- EXPECT_TRUE(checkPixel( 7, 32, 155, 0, 118, 255));
- EXPECT_TRUE(checkPixel(31, 54, 148, 71, 110, 255));
- EXPECT_TRUE(checkPixel(29, 28, 255, 127, 255, 255));
- EXPECT_TRUE(checkPixel(36, 41, 155, 29, 0, 255));
+ EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255));
+ EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255));
+ EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255));
+ EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
+ EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255));
+ EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255));
+ EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
}
TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
@@ -632,6 +655,7 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, 64, 64);
drawTexture();
EXPECT_TRUE(checkPixel( 0, 0, 82, 255, 35, 255));
@@ -649,6 +673,157 @@
}
}
+// This test is intended to catch synchronization bugs between the CPU-written
+// and GPU-read buffers.
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
+ enum { texWidth = 16 };
+ enum { texHeight = 16 };
+ enum { numFrames = 1024 };
+
+ ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+ ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
+ texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
+ ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
+ GRALLOC_USAGE_SW_WRITE_OFTEN));
+
+ struct TestPixel {
+ int x;
+ int y;
+ };
+ const TestPixel testPixels[] = {
+ { 4, 11 },
+ { 12, 14 },
+ { 7, 2 },
+ };
+ enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
+
+ class ProducerThread : public Thread {
+ public:
+ ProducerThread(const sp<ANativeWindow>& anw, const TestPixel* testPixels):
+ mANW(anw),
+ mTestPixels(testPixels) {
+ }
+
+ virtual ~ProducerThread() {
+ }
+
+ virtual bool threadLoop() {
+ for (int i = 0; i < numFrames; i++) {
+ ANativeWindowBuffer* anb;
+ if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+ return false;
+ }
+ if (anb == NULL) {
+ return false;
+ }
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())
+ != NO_ERROR) {
+ return false;
+ }
+
+ const int yuvTexOffsetY = 0;
+ int stride = buf->getStride();
+ int yuvTexStrideY = stride;
+ int yuvTexOffsetV = yuvTexStrideY * texHeight;
+ int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+ int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
+ int yuvTexStrideU = yuvTexStrideV;
+
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+ // Gray out all the test pixels first, so we're more likely to
+ // see a failure if GL is still texturing from the buffer we
+ // just dequeued.
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = mTestPixels[j].x;
+ int y = mTestPixels[j].y;
+ uint8_t value = 128;
+ img[y*stride + x] = value;
+ }
+
+ // Fill the buffer with gray.
+ for (int y = 0; y < texHeight; y++) {
+ for (int x = 0; x < texWidth; x++) {
+ img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
+ img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
+ img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
+ }
+ }
+
+ // Set the test pixels to either white or black.
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = mTestPixels[j].x;
+ int y = mTestPixels[j].y;
+ uint8_t value = 0;
+ if (j == (i % numTestPixels)) {
+ value = 255;
+ }
+ img[y*stride + x] = value;
+ }
+
+ buf->unlock();
+ if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())
+ != NO_ERROR) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ sp<ANativeWindow> mANW;
+ const TestPixel* mTestPixels;
+ };
+
+ sp<FrameWaiter> fw(new FrameWaiter);
+ mST->setFrameAvailableListener(fw);
+
+ sp<Thread> pt(new ProducerThread(mANW, testPixels));
+ pt->run();
+
+ glViewport(0, 0, texWidth, texHeight);
+
+ glClearColor(0.2, 0.2, 0.2, 0.2);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // We wait for the first two frames up front so that the producer will be
+ // likely to dequeue the buffer that's currently being textured from.
+ fw->waitForFrame();
+ fw->waitForFrame();
+
+ for (int i = 0; i < numFrames; i++) {
+ SCOPED_TRACE(String8::format("frame %d", i).string());
+
+ // We must wait for each frame to come in because if we ever do an
+ // updateTexImage call that doesn't consume a newly available buffer
+ // then the producer and consumer will get out of sync, which will cause
+ // a deadlock.
+ if (i > 1) {
+ fw->waitForFrame();
+ }
+ mST->updateTexImage();
+ drawTexture();
+
+ for (int j = 0; j < numTestPixels; j++) {
+ int x = testPixels[j].x;
+ int y = testPixels[j].y;
+ uint8_t value = 0;
+ if (j == (i % numTestPixels)) {
+ // We must y-invert the texture coords
+ EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
+ } else {
+ // We must y-invert the texture coords
+ EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
+ }
+ }
+ }
+
+ pt->requestExitAndWait();
+}
+
// XXX: This test is disabled because there are currently no drivers that can
// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
@@ -679,28 +854,29 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, texWidth, texHeight);
drawTexture();
EXPECT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35));
EXPECT_TRUE(checkPixel(63, 0, 231, 231, 231, 231));
- EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
- EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(63, 65, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35));
EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 63, 35, 231, 231, 35));
- EXPECT_TRUE(checkPixel(19, 40, 87, 179, 35, 35));
+ EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35));
EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35));
EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231));
- EXPECT_TRUE(checkPixel(37, 33, 35, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(37, 33, 228, 38, 38, 38));
EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231));
- EXPECT_TRUE(checkPixel(36, 47, 231, 35, 231, 231));
- EXPECT_TRUE(checkPixel(24, 63, 35, 231, 231, 35));
- EXPECT_TRUE(checkPixel(48, 3, 231, 231, 35, 35));
+ EXPECT_TRUE(checkPixel(36, 47, 228, 35, 231, 231));
+ EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(48, 3, 228, 228, 38, 35));
EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 25, 191, 191, 231, 231));
- EXPECT_TRUE(checkPixel(10, 9, 93, 93, 231, 231));
+ EXPECT_TRUE(checkPixel(24, 25, 41, 41, 231, 231));
+ EXPECT_TRUE(checkPixel(10, 9, 38, 38, 231, 231));
EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231));
- EXPECT_TRUE(checkPixel(56, 31, 35, 231, 231, 35));
+ EXPECT_TRUE(checkPixel(56, 31, 38, 228, 231, 35));
EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231));
}
@@ -734,6 +910,7 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, texWidth, texHeight);
drawTexture();
EXPECT_TRUE(checkPixel( 0, 0, 231, 231, 231, 231));
@@ -807,6 +984,7 @@
glClearColor(0.2, 0.2, 0.2, 0.2);
glClear(GL_COLOR_BUFFER_BIT);
+ glViewport(0, 0, texWidth, texHeight);
drawTexture();
EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 35c8640..450cdf1 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -36,10 +36,10 @@
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
+ SurfaceComposerClient::openGlobalTransaction();
ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
+ SurfaceComposerClient::closeGlobalTransaction();
mSurface = mSurfaceControl->getSurface();
ASSERT_TRUE(mSurface != NULL);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index b0d8cf9..563d7e4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -57,7 +57,7 @@
LOGD("Enabling debug mode %d", mDebugLevel);
#if RENDER_LAYERS_AS_REGIONS
- LOGD("Layers will be composited as regions");
+ INIT_LOGD("Layers will be composited as regions");
#endif
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 596781e..e64d8ac 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -74,7 +74,7 @@
struct CacheLogger {
CacheLogger() {
- LOGD("Creating OpenGL renderer caches");
+ INIT_LOGD("Creating OpenGL renderer caches");
}
}; // struct CacheLogger
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index afab26a..8b1caeee 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -101,8 +101,14 @@
}
mBitmapResources.clear();
+ for (size_t i = 0; i < mFilterResources.size(); i++) {
+ caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+ }
+ mFilterResources.clear();
+
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+ caches.resourceCache.destructor(mShaders.itemAt(i));
}
mShaders.clear();
@@ -151,11 +157,18 @@
caches.resourceCache.incrementRefcount(resource);
}
+ const Vector<SkiaColorFilter*> &filterResources = recorder.getFilterResources();
+ for (size_t i = 0; i < filterResources.size(); i++) {
+ SkiaColorFilter* resource = filterResources.itemAt(i);
+ mFilterResources.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
+ }
+
const Vector<SkiaShader*> &shaders = recorder.getShaders();
for (size_t i = 0; i < shaders.size(); i++) {
- SkiaShader* shader = shaders.itemAt(i);
- mShaders.add(shader);
- caches.resourceCache.incrementRefcount(shader);
+ SkiaShader* resource = shaders.itemAt(i);
+ mShaders.add(resource);
+ caches.resourceCache.incrementRefcount(resource);
}
const Vector<SkPaint*> &paints = recorder.getPaints();
@@ -686,9 +699,10 @@
float* vertices = getFloats(verticesCount);
bool hasColors = getInt();
int* colors = hasColors ? getInts(colorsCount) : NULL;
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
+ renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
}
break;
case DrawPatch: {
@@ -705,9 +719,15 @@
yDivs = getInts(yDivsCount);
colors = getUInts(numColors);
+ float left = getFloat();
+ float top = getFloat();
+ float right = getFloat();
+ float bottom = getFloat();
+ SkPaint* paint = getPaint();
+
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
- numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+ numColors, left, top, right, bottom, paint);
}
break;
case DrawColor: {
@@ -786,15 +806,17 @@
case DrawLines: {
int count = 0;
float* points = getFloats(count);
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawLines(points, count, getPaint());
+ renderer.drawLines(points, count, paint);
}
break;
case DrawPoints: {
int count = 0;
float* points = getFloats(count);
+ SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
- renderer.drawPoints(points, count, getPaint());
+ renderer.drawPoints(points, count, paint);
}
break;
case DrawText: {
@@ -873,21 +895,27 @@
Caches& caches = Caches::getInstance();
for (size_t i = 0; i < mBitmapResources.size(); i++) {
- SkBitmap* resource = mBitmapResources.itemAt(i);
- caches.resourceCache.decrementRefcount(resource);
+ caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
}
mBitmapResources.clear();
+ for (size_t i = 0; i < mFilterResources.size(); i++) {
+ caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
+ }
+ mFilterResources.clear();
+
for (size_t i = 0; i < mShaders.size(); i++) {
- caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+ caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
mShaders.clear();
mShaderMap.clear();
mPaints.clear();
mPaintMap.clear();
+
mPaths.clear();
mPathMap.clear();
+
mMatrices.clear();
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index dcf2cf2..b83259f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -292,6 +292,10 @@
return mBitmapResources;
}
+ const Vector<SkiaColorFilter*>& getFilterResources() const {
+ return mFilterResources;
+ }
+
const Vector<SkiaShader*>& getShaders() const {
return mShaders;
}
@@ -308,10 +312,6 @@
return mMatrices;
}
- const Vector<SkiaColorFilter*>& getFilterResources() const {
- return mFilterResources;
- }
-
private:
void insertRestoreToCount() {
if (mRestoreSaveCount >= 0) {
@@ -419,7 +419,9 @@
inline void addMatrix(SkMatrix* matrix) {
// Copying the matrix is cheap and prevents against the user changing the original
// matrix before the operation that uses it
- addInt((int) new SkMatrix(*matrix));
+ SkMatrix* copy = new SkMatrix(*matrix);
+ addInt((int) copy);
+ mMatrices.add(copy);
}
inline void addBitmap(SkBitmap* bitmap) {
@@ -429,8 +431,7 @@
// which doesn't seem worth the extra cycles for this unlikely case.
addInt((int) bitmap);
mBitmapResources.add(bitmap);
- Caches& caches = Caches::getInstance();
- caches.resourceCache.incrementRefcount(bitmap);
+ Caches::getInstance().resourceCache.incrementRefcount(bitmap);
}
inline void addShader(SkiaShader* shader) {
@@ -454,8 +455,7 @@
inline void addColorFilter(SkiaColorFilter* colorFilter) {
addInt((int) colorFilter);
mFilterResources.add(colorFilter);
- Caches& caches = Caches::getInstance();
- caches.resourceCache.incrementRefcount(colorFilter);
+ Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
}
Vector<SkBitmap*> mBitmapResources;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 146e789..e034a868 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -166,30 +166,6 @@
// Layers management
///////////////////////////////////////////////////////////////////////////////
-Layer* LayerRenderer::createTextureLayer() {
- LAYER_RENDERER_LOGD("Creating new texture layer");
-
- Layer* layer = new Layer(0, 0);
- layer->isCacheable = false;
- layer->isTextureLayer = true;
- layer->blend = true;
- layer->empty = true;
- layer->fbo = 0;
- layer->colorFilter = NULL;
- layer->fbo = 0;
- layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
- layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
- layer->alpha = 255;
- layer->mode = SkXfermode::kSrcOver_Mode;
- layer->colorFilter = NULL;
- layer->region.clear();
-
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &layer->texture);
-
- return layer;
-}
-
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
@@ -269,24 +245,56 @@
return true;
}
+static void setTextureParameters(Layer* layer) {
+ glBindTexture(layer->renderTarget, layer->texture);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
+ LAYER_RENDERER_LOGD("Creating new texture layer");
+
+ Layer* layer = new Layer(0, 0);
+ layer->isCacheable = false;
+ layer->isTextureLayer = true;
+ layer->blend = !isOpaque;
+ layer->empty = true;
+ layer->fbo = 0;
+ layer->colorFilter = NULL;
+ layer->fbo = 0;
+ layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
+ layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+ layer->alpha = 255;
+ layer->mode = SkXfermode::kSrcOver_Mode;
+ layer->colorFilter = NULL;
+ layer->region.clear();
+ layer->renderTarget = GL_NONE; // see ::updateTextureLayer()
+
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1, &layer->texture);
+
+ return layer;
+}
+
void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
- GLenum renderTarget, float* transform) {
+ bool isOpaque, GLenum renderTarget, float* transform) {
if (layer) {
+ layer->blend = !isOpaque;
layer->width = width;
layer->height = height;
layer->layer.set(0.0f, 0.0f, width, height);
layer->region.set(width, height);
layer->regionRect.set(0.0f, 0.0f, width, height);
layer->texTransform.load(transform);
- layer->renderTarget = renderTarget;
- glBindTexture(layer->renderTarget, layer->texture);
-
- glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (renderTarget != layer->renderTarget) {
+ layer->renderTarget = renderTarget;
+ setTextureParameters(layer);
+ }
}
}
@@ -326,12 +334,17 @@
return false;
}
+ SkAutoLockPixels alp(*bitmap);
+
GLuint texture;
GLuint previousFbo;
GLenum format;
GLenum type;
+ GLenum error = GL_NO_ERROR;
+ bool status = false;
+
switch (bitmap->config()) {
case SkBitmap::kA8_Config:
format = GL_ALPHA;
@@ -352,10 +365,18 @@
break;
}
+ float alpha = layer->alpha;
+ SkXfermode::Mode mode = layer->mode;
+
+ layer->mode = SkXfermode::kSrc_Mode;
+ layer->alpha = 255;
+ layer->fbo = fbo;
+
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &texture);
+ if ((error = glGetError()) != GL_NO_ERROR) goto error;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
@@ -368,39 +389,48 @@
glTexImage2D(GL_TEXTURE_2D, 0, format, bitmap->width(), bitmap->height(),
0, format, type, NULL);
+ if ((error = glGetError()) != GL_NO_ERROR) goto error;
+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
+ if ((error = glGetError()) != GL_NO_ERROR) goto error;
- glBindTexture(GL_TEXTURE_2D, layer->texture);
+ {
+ LayerRenderer renderer(layer);
+ renderer.setViewport(bitmap->width(), bitmap->height());
+ renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
+ bitmap->width(), bitmap->height(), !layer->blend);
+ if ((error = glGetError()) != GL_NO_ERROR) goto error;
- float alpha = layer->alpha;
- SkXfermode::Mode mode = layer->mode;
+ {
+ Rect bounds;
+ bounds.set(0.0f, 0.0f, bitmap->width(), bitmap->height());
+ renderer.drawTextureLayer(layer, bounds);
- layer->mode = SkXfermode::kSrc_Mode;
- layer->alpha = 255;
- layer->fbo = fbo;
+ glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
+ type, bitmap->getPixels());
- LayerRenderer renderer(layer);
- renderer.setViewport(bitmap->width(), bitmap->height());
- renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
- bitmap->width(), bitmap->height(), !layer->blend);
+ if ((error = glGetError()) != GL_NO_ERROR) goto error;
+ }
- Rect bounds;
- bounds.set(0.0f, 0.0f, bitmap->width(), bitmap->height());
- renderer.drawTextureLayer(layer, bounds);
+ status = true;
+ }
- SkAutoLockPixels alp(*bitmap);
- glReadPixels(0, 0, bitmap->width(), bitmap->height(), format, type, bitmap->getPixels());
+error:
+#if DEBUG_OPENGL
+ if (error != GL_NO_ERROR) {
+ LOGD("GL error while copying layer into bitmap = 0x%x", error);
+ }
+#endif
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-
layer->mode = mode;
layer->alpha = alpha;
layer->fbo = 0;
glDeleteTextures(1, &texture);
caches.fboCache.put(fbo);
- return true;
+ return status;
}
return false;
}
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 797dfc6..2246573 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -55,11 +55,11 @@
Region* getRegion();
GLint getTargetFbo();
- static Layer* createTextureLayer();
+ static Layer* createTextureLayer(bool isOpaque);
static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
- GLenum renderTarget, float* transform);
+ bool isOpaque, GLenum renderTarget, float* transform);
static void destroyLayer(Layer* layer);
static void destroyLayerDeferred(Layer* layer);
static bool copyLayer(Layer* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5343a05..1c06a0b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -151,7 +151,6 @@
mSaveCount = 1;
glViewport(0, 0, mWidth, mHeight);
-
glDisable(GL_DITHER);
glEnable(GL_SCISSOR_TEST);
@@ -640,7 +639,7 @@
setupDrawTextureTransform();
setupDrawColor(alpha, alpha, alpha, alpha);
setupDrawColorFilter();
- setupDrawBlending(layer->blend, layer->mode);
+ setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode);
setupDrawProgram();
setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
setupDrawPureColorUniforms();
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 9aade51..cd2c405 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -48,9 +48,6 @@
void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
Mutex::Autolock _l(mLock);
- for (size_t i = 0; i < mCache->size(); ++i) {
- void* ref = mCache->valueAt(i);
- }
ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
if (ref == NULL || mCache->size() == 0) {
ref = new ResourceReference(resourceType);
@@ -144,7 +141,6 @@
ref->destroyed = true;
if (ref->refCount == 0) {
deleteResourceReference(resource, ref);
- return;
}
}
@@ -162,7 +158,6 @@
ref->destroyed = true;
if (ref->refCount == 0) {
deleteResourceReference(resource, ref);
- return;
}
}
@@ -180,7 +175,6 @@
ref->destroyed = true;
if (ref->refCount == 0) {
deleteResourceReference(resource, ref);
- return;
}
}
@@ -195,7 +189,6 @@
ref->destroyed = true;
if (ref->refCount == 0) {
deleteResourceReference(resource, ref);
- return;
}
}
@@ -209,36 +202,32 @@
}
if (ref->destroyed) {
switch (ref->resourceType) {
- case kBitmap:
- {
- SkBitmap* bitmap = (SkBitmap*)resource;
+ case kBitmap: {
+ SkBitmap* bitmap = (SkBitmap*) resource;
if (Caches::hasInstance()) {
Caches::getInstance().textureCache.removeDeferred(bitmap);
}
delete bitmap;
}
break;
- case kPath:
- {
- SkPath* path = (SkPath*)resource;
+ case kPath: {
+ SkPath* path = (SkPath*) resource;
if (Caches::hasInstance()) {
Caches::getInstance().pathCache.removeDeferred(path);
}
delete path;
}
break;
- case kShader:
- {
- SkiaShader* shader = (SkiaShader*)resource;
+ case kShader: {
+ SkiaShader* shader = (SkiaShader*) resource;
if (Caches::hasInstance()) {
Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
}
delete shader;
}
break;
- case kColorFilter:
- {
- SkiaColorFilter* filter = (SkiaColorFilter*)resource;
+ case kColorFilter: {
+ SkiaColorFilter* filter = (SkiaColorFilter*) resource;
delete filter;
}
break;
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index b5cc29c..b048469 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -537,15 +537,16 @@
const float pathWidth = fmax(bounds.width(), 1.0f);
const float pathHeight = fmax(bounds.height(), 1.0f);
- if (pathWidth > mMaxTextureSize || pathHeight > mMaxTextureSize) {
+ const float offset = fmax(paint->getStrokeWidth(), 1.0f) * 1.5f;
+
+ const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
+ const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
+
+ if (width > mMaxTextureSize || height > mMaxTextureSize) {
LOGW("Shape %s too large to be rendered into a texture", mName);
return NULL;
}
- const float offset = paint->getStrokeWidth() * 1.5f;
- const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
- const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
-
const uint32_t size = width * height;
// Don't even try to cache a bitmap that's bigger than the cache
if (size < mMaxSize) {
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index bf45e13..1bf475c 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -59,7 +59,7 @@
return mType;
}
- SkColorFilter *getSkColorFilter() {
+ SkColorFilter* getSkColorFilter() {
return mSkFilter;
}
diff --git a/libs/rs/driver/rsdAllocation.cpp b/libs/rs/driver/rsdAllocation.cpp
index 01a0cf6..17dd931 100644
--- a/libs/rs/driver/rsdAllocation.cpp
+++ b/libs/rs/driver/rsdAllocation.cpp
@@ -460,8 +460,8 @@
uint8_t *srcPtr = getOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
memcpy(dstPtr, srcPtr, w * elementSize);
- LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
- dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
+ //LOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
+ // dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
}
}
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 3ff03b4..1f7bb0f 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -321,8 +321,13 @@
dc->gl.height = 1;
}
+ if (dc->gl.wndSurface != NULL) {
+ dc->gl.wndSurface->decStrong(NULL);
+ }
+
dc->gl.wndSurface = (ANativeWindow *)sur;
if (dc->gl.wndSurface != NULL) {
+ dc->gl.wndSurface->incStrong(NULL);
dc->gl.width = w;
dc->gl.height = h;
diff --git a/libs/rs/driver/rsdRuntimeMath.cpp b/libs/rs/driver/rsdRuntimeMath.cpp
index acb990d..d29da7e 100644
--- a/libs/rs/driver/rsdRuntimeMath.cpp
+++ b/libs/rs/driver/rsdRuntimeMath.cpp
@@ -268,6 +268,87 @@
}
+static int32_t SC_AtomicCas(volatile int32_t *ptr, int32_t expectedValue, int32_t newValue) {
+ int32_t prev;
+
+ do {
+ int32_t ret = android_atomic_release_cas(expectedValue, newValue, ptr);
+ if (!ret) {
+ // The android cas return 0 if it wrote the value. This means the
+ // previous value was the expected value and we can return.
+ return expectedValue;
+ }
+ // We didn't write the value and need to load the "previous" value.
+ prev = *ptr;
+
+ // A race condition exists where the expected value could appear after our cas failed
+ // above. In this case loop until we have a legit previous value or the
+ // write passes.
+ } while (prev == expectedValue);
+ return prev;
+}
+
+
+static int32_t SC_AtomicInc(volatile int32_t *ptr) {
+ return android_atomic_inc(ptr);
+}
+
+static int32_t SC_AtomicDec(volatile int32_t *ptr) {
+ return android_atomic_dec(ptr);
+}
+
+static int32_t SC_AtomicAdd(volatile int32_t *ptr, int32_t value) {
+ return android_atomic_add(value, ptr);
+}
+
+static int32_t SC_AtomicSub(volatile int32_t *ptr, int32_t value) {
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_release_cas(prev, prev - value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+static int32_t SC_AtomicAnd(volatile int32_t *ptr, int32_t value) {
+ return android_atomic_and(value, ptr);
+}
+
+static int32_t SC_AtomicOr(volatile int32_t *ptr, int32_t value) {
+ return android_atomic_or(value, ptr);
+}
+
+static int32_t SC_AtomicXor(volatile int32_t *ptr, int32_t value) {
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_release_cas(prev, prev ^ value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+static int32_t SC_AtomicMin(volatile int32_t *ptr, int32_t value) {
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ int32_t n = rsMin(value, prev);
+ status = android_atomic_release_cas(prev, n, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+static int32_t SC_AtomicMax(volatile int32_t *ptr, int32_t value) {
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ int32_t n = rsMax(value, prev);
+ status = android_atomic_release_cas(prev, n, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+
+
//////////////////////////////////////////////////////////////////////////////
// Class implementation
//////////////////////////////////////////////////////////////////////////////
@@ -425,6 +506,28 @@
{ "_Z6rsRandff", (void *)&SC_randf2, true },
{ "_Z6rsFracf", (void *)&SC_frac, true },
+ // Atomics
+ { "_Z11rsAtomicIncPVi", (void *)&SC_AtomicInc, true },
+ { "_Z11rsAtomicIncPVj", (void *)&SC_AtomicInc, true },
+ { "_Z11rsAtomicDecPVi", (void *)&SC_AtomicDec, true },
+ { "_Z11rsAtomicDecPVj", (void *)&SC_AtomicDec, true },
+ { "_Z11rsAtomicAddPVii", (void *)&SC_AtomicAdd, true },
+ { "_Z11rsAtomicAddPVjj", (void *)&SC_AtomicAdd, true },
+ { "_Z11rsAtomicSubPVii", (void *)&SC_AtomicSub, true },
+ { "_Z11rsAtomicSubPVjj", (void *)&SC_AtomicSub, true },
+ { "_Z11rsAtomicAndPVii", (void *)&SC_AtomicAnd, true },
+ { "_Z11rsAtomicAndPVjj", (void *)&SC_AtomicAnd, true },
+ { "_Z10rsAtomicOrPVii", (void *)&SC_AtomicOr, true },
+ { "_Z10rsAtomicOrPVjj", (void *)&SC_AtomicOr, true },
+ { "_Z11rsAtomicXorPVii", (void *)&SC_AtomicXor, true },
+ { "_Z11rsAtomicXorPVjj", (void *)&SC_AtomicXor, true },
+ { "_Z11rsAtomicMinPVii", (void *)&SC_AtomicMin, true },
+ { "_Z11rsAtomicMinPVjj", (void *)&SC_AtomicMin, true },
+ { "_Z11rsAtomicMaxPVii", (void *)&SC_AtomicMax, true },
+ { "_Z11rsAtomicMaxPVjj", (void *)&SC_AtomicMax, true },
+ { "_Z11rsAtomicCasPViii", (void *)&SC_AtomicCas, true },
+ { "_Z11rsAtomicCasPVjjj", (void *)&SC_AtomicCas, true },
+
{ NULL, NULL, false }
};
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 25302aa..2f9f410 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -525,10 +525,6 @@
// ::= d # double
static RsdSymbolTable gSyms[] = {
- { "__divsi3", (void *)&SC_divsi3, true },
- { "__modsi3", (void *)&SC_modsi3, true },
- { "__udivsi3", (void *)&SC_udivsi3, true },
- { "__umodsi3", (void *)&SC_umodsi3, true },
{ "memset", (void *)&memset, true },
{ "memcpy", (void *)&memcpy, true },
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 963a6e7..0dea971 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -103,6 +103,7 @@
param uint32_t width
param uint32_t height
param RsNativeWindow sur
+ sync
}
ContextDump {
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index 584317e..f38f72c 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -258,4 +258,226 @@
rs_allocation output, const void * usrData,
const rs_script_call_t *);
+
+
+/**
+ * Atomic add one to the value at addr.
+ * Equal to rsAtomicAdd(addr, 1)
+ *
+ * @param addr Address of value to increment
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicInc(volatile int32_t* addr);
+/**
+ * Atomic add one to the value at addr.
+ * Equal to rsAtomicAdd(addr, 1)
+ *
+ * @param addr Address of value to increment
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicInc(volatile uint32_t* addr);
+
+/**
+ * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1)
+ *
+ * @param addr Address of value to decrement
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicDec(volatile int32_t* addr);
+/**
+ * Atomic subtract one from the value at addr. Equal to rsAtomicSub(addr, 1)
+ *
+ * @param addr Address of value to decrement
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicDec(volatile uint32_t* addr);
+
+/**
+ * Atomic add a value to the value at addr. addr[0] += value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to add to the value at addr
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicAdd(volatile int32_t* addr, int32_t value);
+/**
+ * Atomic add a value to the value at addr. addr[0] += value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to add to the value at addr
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicAdd(volatile uint32_t* addr, uint32_t value);
+
+/**
+ * Atomic Subtract a value from the value at addr. addr[0] -= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to subtract from the value at addr
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicSub(volatile int32_t* addr, int32_t value);
+/**
+ * Atomic Subtract a value from the value at addr. addr[0] -= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to subtract from the value at addr
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicSub(volatile uint32_t* addr, uint32_t value);
+
+/**
+ * Atomic Bitwise and a value from the value at addr. addr[0] &= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to and with the value at addr
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicAnd(volatile int32_t* addr, int32_t value);
+/**
+ * Atomic Bitwise and a value from the value at addr. addr[0] &= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to and with the value at addr
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicAnd(volatile uint32_t* addr, uint32_t value);
+
+/**
+ * Atomic Bitwise or a value from the value at addr. addr[0] |= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to or with the value at addr
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicOr(volatile int32_t* addr, int32_t value);
+/**
+ * Atomic Bitwise or a value from the value at addr. addr[0] |= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to or with the value at addr
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicOr(volatile uint32_t* addr, uint32_t value);
+
+/**
+ * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to xor with the value at addr
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicXor(volatile uint32_t* addr, uint32_t value);
+/**
+ * Atomic Bitwise xor a value from the value at addr. addr[0] ^= value
+ *
+ * @param addr Address of value to modify
+ * @param value Amount to xor with the value at addr
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicXor(volatile int32_t* addr, int32_t value);
+
+/**
+ * Atomic Set the value at addr to the min of addr and value
+ * addr[0] = rsMin(addr[0], value)
+ *
+ * @param addr Address of value to modify
+ * @param value comparison value
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicMin(volatile uint32_t* addr, uint32_t value);
+/**
+ * Atomic Set the value at addr to the min of addr and value
+ * addr[0] = rsMin(addr[0], value)
+ *
+ * @param addr Address of value to modify
+ * @param value comparison value
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicMin(volatile int32_t* addr, int32_t value);
+
+/**
+ * Atomic Set the value at addr to the max of addr and value
+ * addr[0] = rsMax(addr[0], value)
+ *
+ * @param addr Address of value to modify
+ * @param value comparison value
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicMax(volatile uint32_t* addr, uint32_t value);
+/**
+ * Atomic Set the value at addr to the max of addr and value
+ * addr[0] = rsMin(addr[0], value)
+ *
+ * @param addr Address of value to modify
+ * @param value comparison value
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicMax(volatile int32_t* addr, int32_t value);
+
+/**
+ * Compare-and-set operation with a full memory barrier.
+ *
+ * If the value at addr matches compareValue then newValue is written.
+ *
+ * @param addr The address to compare and replace if the compare passes.
+ * @param compareValue The value to test addr[0] against.
+ * @param newValue The value to write if the test passes.
+ *
+ * @return old value
+ */
+extern int32_t __attribute__((overloadable))
+ rsAtomicCas(volatile int32_t* addr, int32_t compareValue, int32_t newValue);
+
+/**
+ * Compare-and-set operation with a full memory barrier.
+ *
+ * If the value at addr matches compareValue then newValue is written.
+ *
+ * @param addr The address to compare and replace if the compare passes.
+ * @param compareValue The value to test addr[0] against.
+ * @param newValue The value to write if the test passes.
+ *
+ * @return old value
+ */
+extern uint32_t __attribute__((overloadable))
+ rsAtomicCas(volatile uint32_t* addr, int32_t compareValue, int32_t newValue);
+
+
#endif
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f9990bb..427bbba 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,7 +43,6 @@
LOCAL_SRC_FILES:= \
$(commonSources) \
EGLUtils.cpp \
- EventRecurrence.cpp \
FramebufferNativeWindow.cpp \
GraphicBuffer.cpp \
GraphicBufferAllocator.cpp \
diff --git a/libs/ui/EventRecurrence.cpp b/libs/ui/EventRecurrence.cpp
deleted file mode 100644
index b436b50..0000000
--- a/libs/ui/EventRecurrence.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright 2006 The Android Open Source Project
- */
-
-#include <pim/EventRecurrence.h>
-#include <utils/String8.h>
-#include <stdio.h>
-#include <limits.h>
-
-namespace android {
-
-#define FAIL_HERE() do { \
- printf("Parsing failed at line %d\n", __LINE__); \
- return UNKNOWN_ERROR; \
- } while(0)
-
-EventRecurrence::EventRecurrence()
- :freq((freq_t)0),
- until(),
- count(0),
- interval(0),
- bysecond(0),
- bysecondCount(0),
- byminute(0),
- byminuteCount(0),
- byhour(0),
- byhourCount(0),
- byday(0),
- bydayNum(0),
- bydayCount(0),
- bymonthday(0),
- bymonthdayCount(0),
- byyearday(0),
- byyeardayCount(0),
- byweekno(0),
- byweeknoCount(0),
- bymonth(0),
- bymonthCount(0),
- bysetpos(0),
- bysetposCount(0),
- wkst(0)
-{
-}
-
-EventRecurrence::~EventRecurrence()
-{
- delete[] bysecond;
- delete[] byminute;
- delete[] byhour;
- delete[] byday;
- delete[] bydayNum;
- delete[] byyearday;
- delete[] bymonthday;
- delete[] byweekno;
- delete[] bymonth;
- delete[] bysetpos;
-}
-
-enum LHS {
- NONE_LHS = 0,
- FREQ,
- UNTIL,
- COUNT,
- INTERVAL,
- BYSECOND,
- BYMINUTE,
- BYHOUR,
- BYDAY,
- BYMONTHDAY,
- BYYEARDAY,
- BYWEEKNO,
- BYMONTH,
- BYSETPOS,
- WKST
-};
-
-struct LHSProc
-{
- const char16_t* text;
- size_t textSize;
- uint32_t value;
-};
-
-const char16_t FREQ_text[] = { 'F', 'R', 'E', 'Q' };
-const char16_t UNTIL_text[] = { 'U', 'N', 'T', 'I', 'L' };
-const char16_t COUNT_text[] = { 'C', 'O', 'U', 'N', 'T' };
-const char16_t INTERVAL_text[] = { 'I', 'N', 'T', 'E', 'R', 'V', 'A', 'L'};
-const char16_t BYSECOND_text[] = { 'B', 'Y', 'S', 'E', 'C', 'O', 'N', 'D' };
-const char16_t BYMINUTE_text[] = { 'B', 'Y', 'M', 'I', 'N', 'U', 'T', 'E' };
-const char16_t BYHOUR_text[] = { 'B', 'Y', 'H', 'O', 'U', 'R' };
-const char16_t BYDAY_text[] = { 'B', 'Y', 'D', 'A', 'Y' };
-const char16_t BYMONTHDAY_text[] = { 'B','Y','M','O','N','T','H','D','A','Y' };
-const char16_t BYYEARDAY_text[] = { 'B','Y','Y','E','A','R','D','A','Y' };
-const char16_t BYWEEKNO_text[] = { 'B', 'Y', 'W', 'E', 'E', 'K', 'N', 'O' };
-const char16_t BYMONTH_text[] = { 'B', 'Y', 'M', 'O', 'N', 'T', 'H' };
-const char16_t BYSETPOS_text[] = { 'B', 'Y', 'S', 'E', 'T', 'P', 'O', 'S' };
-const char16_t WKST_text[] = { 'W', 'K', 'S', 'T' };
-
-#define SIZ(x) (sizeof(x)/sizeof(x[0]))
-
-const LHSProc LHSPROC[] = {
- { FREQ_text, SIZ(FREQ_text), FREQ },
- { UNTIL_text, SIZ(UNTIL_text), UNTIL },
- { COUNT_text, SIZ(COUNT_text), COUNT },
- { INTERVAL_text, SIZ(INTERVAL_text), INTERVAL },
- { BYSECOND_text, SIZ(BYSECOND_text), BYSECOND },
- { BYMINUTE_text, SIZ(BYMINUTE_text), BYMINUTE },
- { BYHOUR_text, SIZ(BYHOUR_text), BYHOUR },
- { BYDAY_text, SIZ(BYDAY_text), BYDAY },
- { BYMONTHDAY_text, SIZ(BYMONTHDAY_text), BYMONTHDAY },
- { BYYEARDAY_text, SIZ(BYYEARDAY_text), BYYEARDAY },
- { BYWEEKNO_text, SIZ(BYWEEKNO_text), BYWEEKNO },
- { BYMONTH_text, SIZ(BYMONTH_text), BYMONTH },
- { BYSETPOS_text, SIZ(BYSETPOS_text), BYSETPOS },
- { WKST_text, SIZ(WKST_text), WKST },
- { NULL, 0, NONE_LHS },
-};
-
-const char16_t SECONDLY_text[] = { 'S','E','C','O','N','D','L','Y' };
-const char16_t MINUTELY_text[] = { 'M','I','N','U','T','E','L','Y' };
-const char16_t HOURLY_text[] = { 'H','O','U','R','L','Y' };
-const char16_t DAILY_text[] = { 'D','A','I','L','Y' };
-const char16_t WEEKLY_text[] = { 'W','E','E','K','L','Y' };
-const char16_t MONTHLY_text[] = { 'M','O','N','T','H','L','Y' };
-const char16_t YEARLY_text[] = { 'Y','E','A','R','L','Y' };
-
-typedef LHSProc FreqProc;
-
-const FreqProc FREQPROC[] = {
- { SECONDLY_text, SIZ(SECONDLY_text), EventRecurrence::SECONDLY },
- { MINUTELY_text, SIZ(MINUTELY_text), EventRecurrence::MINUTELY },
- { HOURLY_text, SIZ(HOURLY_text), EventRecurrence::HOURLY },
- { DAILY_text, SIZ(DAILY_text), EventRecurrence::DAILY },
- { WEEKLY_text, SIZ(WEEKLY_text), EventRecurrence::WEEKLY },
- { MONTHLY_text, SIZ(MONTHLY_text), EventRecurrence::MONTHLY },
- { YEARLY_text, SIZ(YEARLY_text), EventRecurrence::YEARLY },
- { NULL, 0, NONE_LHS },
-};
-
-const char16_t SU_text[] = { 'S','U' };
-const char16_t MO_text[] = { 'M','O' };
-const char16_t TU_text[] = { 'T','U' };
-const char16_t WE_text[] = { 'W','E' };
-const char16_t TH_text[] = { 'T','H' };
-const char16_t FR_text[] = { 'F','R' };
-const char16_t SA_text[] = { 'S','A' };
-
-const FreqProc WEEKDAYPROC[] = {
- { SU_text, SIZ(SU_text), EventRecurrence::SU },
- { MO_text, SIZ(MO_text), EventRecurrence::MO },
- { TU_text, SIZ(TU_text), EventRecurrence::TU },
- { WE_text, SIZ(WE_text), EventRecurrence::WE },
- { TH_text, SIZ(TH_text), EventRecurrence::TH },
- { FR_text, SIZ(FR_text), EventRecurrence::FR },
- { SA_text, SIZ(SA_text), EventRecurrence::SA },
- { NULL, 0, NONE_LHS },
-};
-
-// returns the index into LHSPROC for the match or -1 if not found
-inline static int
-match_proc(const LHSProc* p, const char16_t* str, size_t len)
-{
- int i = 0;
- while (p->text != NULL) {
- if (p->textSize == len) {
- if (0 == memcmp(p->text, str, len*sizeof(char16_t))) {
- return i;
- }
- }
- p++;
- i++;
- }
- return -1;
-}
-
-// rangeMin and rangeMax are inclusive
-static status_t
-parse_int(const char16_t* str, size_t len, int* out,
- int rangeMin, int rangeMax, bool zeroOK)
-{
- char16_t c;
- size_t i=0;
-
- if (len == 0) {
- FAIL_HERE();
- }
- bool negative = false;
- c = str[0];
- if (c == '-' ) {
- negative = true;
- i++;
- }
- else if (c == '+') {
- i++;
- }
- int n = 0;
- for (; i<len; i++) {
- c = str[i];
- if (c < '0' || c > '9') {
- FAIL_HERE();
- }
- int prev = n;
- n *= 10;
- // the spec doesn't address how big these numbers can be,
- // so we're not going to worry about not being able to represent
- // INT_MIN, and if we're going to wrap, we'll just clamp to
- // INT_MAX instead
- if (n < prev) {
- n = INT_MAX;
- } else {
- n += c - '0';
- }
- }
- if (negative) {
- n = -n;
- }
- if (n < rangeMin || n > rangeMax) {
- FAIL_HERE();
- }
- if (!zeroOK && n == 0) {
- FAIL_HERE();
- }
- *out = n;
- return NO_ERROR;
-}
-
-static status_t
-parse_int_list(const char16_t* str, size_t len, int* countOut, int** listOut,
- int rangeMin, int rangeMax, bool zeroOK,
- status_t (*func)(const char16_t*,size_t,int*,int,int,bool)=parse_int)
-{
- status_t err;
-
- if (len == 0) {
- *countOut = 0;
- *listOut = NULL;
- return NO_ERROR;
- }
-
- // make one pass through looking for commas so we know how big to make our
- // out array.
- int count = 1;
- for (size_t i=0; i<len; i++) {
- if (str[i] == ',') {
- count++;
- }
- }
-
- int* list = new int[count];
- const char16_t* p = str;
- int commaIndex = 0;
- size_t i;
-
- for (i=0; i<len; i++) {
- if (str[i] == ',') {
- err = func(p, (str+i-p), list+commaIndex, rangeMin,
- rangeMax, zeroOK);
- if (err != NO_ERROR) {
- goto bail;
- }
- commaIndex++;
- p = str+i+1;
- }
- }
-
- err = func(p, (str+i-p), list+commaIndex, rangeMin, rangeMax, zeroOK);
- if (err != NO_ERROR) {
- goto bail;
- }
- commaIndex++;
-
- *countOut = count;
- *listOut = list;
-
- return NO_ERROR;
-
-bail:
- delete[] list;
- FAIL_HERE();
-}
-
-// the numbers here are small, so we pack them both into one value, and then
-// split it out later. it lets us reuse all the comma separated list code.
-static status_t
-parse_byday(const char16_t* s, size_t len, int* out,
- int rangeMin, int rangeMax, bool zeroOK)
-{
- status_t err;
- int n = 0;
- const char16_t* p = s;
- size_t plen = len;
-
- if (len > 0) {
- char16_t c = s[0];
- if (c == '-' || c == '+' || (c >= '0' && c <= '9')) {
- if (len > 1) {
- size_t nlen = 0;
- c = s[nlen];
- while (nlen < len
- && (c == '-' || c == '+' || (c >= '0' && c <= '9'))) {
- c = s[nlen];
- nlen++;
- }
- if (nlen > 0) {
- nlen--;
- err = parse_int(s, nlen, &n, rangeMin, rangeMax, zeroOK);
- if (err != NO_ERROR) {
- FAIL_HERE();
- }
- p += nlen;
- plen -= nlen;
- }
- }
- }
-
- int index = match_proc(WEEKDAYPROC, p, plen);
- if (index >= 0) {
- *out = (0xffff0000 & WEEKDAYPROC[index].value)
- | (0x0000ffff & n);
- return NO_ERROR;
- }
- }
- return UNKNOWN_ERROR;
-}
-
-static void
-postprocess_byday(int count, int* byday, int** bydayNum)
-{
- int* bdn = new int[count];
- *bydayNum = bdn;
- for (int i=0; i<count; i++) {
- uint32_t v = byday[i];
- int16_t num = v & 0x0000ffff;
- byday[i] = v & 0xffff0000;
- // will sign extend:
- bdn[i] = num;
- }
-}
-
-#define PARSE_INT_LIST_CHECKED(name, rangeMin, rangeMax, zeroOK) \
- if (name##Count != 0 || NO_ERROR != parse_int_list(s, slen, \
- &name##Count, &name, rangeMin, rangeMax, zeroOK)) { \
- FAIL_HERE(); \
- }
-status_t
-EventRecurrence::parse(const String16& str)
-{
- char16_t const* work = str.string();
- size_t len = str.size();
-
- int lhsIndex = NONE_LHS;
- int index;
-
- size_t start = 0;
- for (size_t i=0; i<len; i++) {
- char16_t c = work[i];
- if (c != ';' && i == len-1) {
- c = ';';
- i++;
- }
- if (c == ';' || c == '=') {
- if (i != start) {
- const char16_t* s = work+start;
- const size_t slen = i-start;
-
- String8 thestring(String16(s, slen));
-
- switch (c)
- {
- case '=':
- if (lhsIndex == NONE_LHS) {
- lhsIndex = match_proc(LHSPROC, s, slen);
- if (lhsIndex >= 0) {
- break;
- }
- }
- FAIL_HERE();
- case ';':
- {
- switch (LHSPROC[lhsIndex].value)
- {
- case FREQ:
- if (this->freq != 0) {
- FAIL_HERE();
- }
- index = match_proc(FREQPROC, s, slen);
- if (index >= 0) {
- this->freq = (freq_t)FREQPROC[index].value;
- }
- break;
- case UNTIL:
- // XXX should check that this is a valid time
- until.setTo(String16(s, slen));
- break;
- case COUNT:
- if (count != 0
- || NO_ERROR != parse_int(s, slen,
- &count, INT_MIN, INT_MAX, true)) {
- FAIL_HERE();
- }
- break;
- case INTERVAL:
- if (interval != 0
- || NO_ERROR != parse_int(s, slen,
- &interval, INT_MIN, INT_MAX, false)) {
- FAIL_HERE();
- }
- break;
- case BYSECOND:
- PARSE_INT_LIST_CHECKED(bysecond, 0, 59, true)
- break;
- case BYMINUTE:
- PARSE_INT_LIST_CHECKED(byminute, 0, 59, true)
- break;
- case BYHOUR:
- PARSE_INT_LIST_CHECKED(byhour, 0, 23, true)
- break;
- case BYDAY:
- if (bydayCount != 0 || NO_ERROR !=
- parse_int_list(s, slen, &bydayCount,
- &byday, -53, 53, false,
- parse_byday)) {
- FAIL_HERE();
- }
- postprocess_byday(bydayCount, byday, &bydayNum);
- break;
- case BYMONTHDAY:
- PARSE_INT_LIST_CHECKED(bymonthday, -31, 31,
- false)
- break;
- case BYYEARDAY:
- PARSE_INT_LIST_CHECKED(byyearday, -366, 366,
- false)
- break;
- case BYWEEKNO:
- PARSE_INT_LIST_CHECKED(byweekno, -53, 53,
- false)
- break;
- case BYMONTH:
- PARSE_INT_LIST_CHECKED(bymonth, 1, 12, false)
- break;
- case BYSETPOS:
- PARSE_INT_LIST_CHECKED(bysetpos,
- INT_MIN, INT_MAX, true)
- break;
- case WKST:
- if (this->wkst != 0) {
- FAIL_HERE();
- }
- index = match_proc(WEEKDAYPROC, s, slen);
- if (index >= 0) {
- this->wkst = (int)WEEKDAYPROC[index].value;
- }
- break;
- default:
- FAIL_HERE();
- }
- lhsIndex = NONE_LHS;
- break;
- }
- }
-
- start = i+1;
- }
- }
- }
-
- // enforce that there was a FREQ
- if (freq == 0) {
- FAIL_HERE();
- }
-
- // default wkst to MO if it wasn't specified
- if (wkst == 0) {
- wkst = MO;
- }
-
- return NO_ERROR;
-}
-
-
-}; // namespace android
-
-
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index ffdfe66..c46d6f4 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -443,7 +443,8 @@
if (! mPinned || ! mMotionEventSampleDataTail) {
LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
- "AMOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+ "AMOTION_EVENT_ACTION_MOVE or AMOTION_EVENT_ACTION_HOVER_MOVE event.",
+ mChannel->getName().string());
return INVALID_OPERATION;
}
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 093189c..774e8c9 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -27,6 +27,7 @@
Debug.cpp \
FileMap.cpp \
Flattenable.cpp \
+ LinearTransform.cpp \
ObbFile.cpp \
Pool.cpp \
PropertyMap.cpp \
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index f963058..87912639 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -285,7 +285,8 @@
break;
}
default:
- LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type);
+ LOGD("Chunk header at %d has invalid type: 0x%08x",
+ (int)(m_pos - sizeof(m_header)), (int)m_header.type);
m_status = EINVAL;
}
diff --git a/libs/utils/LinearTransform.cpp b/libs/utils/LinearTransform.cpp
new file mode 100644
index 0000000..d752415
--- /dev/null
+++ b/libs/utils/LinearTransform.cpp
@@ -0,0 +1,262 @@
+/*
+ * 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+static bool scale_u64_to_u64(
+ uint64_t val,
+ uint32_t N,
+ uint32_t D,
+ uint64_t* res,
+ bool round_up_not_down) {
+ uint64_t tmp1, tmp2;
+ uint32_t r;
+
+ assert(res);
+ assert(D);
+
+ // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+ // integer X.
+ // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+ // integer X.
+ // Let X[A, B] with A <= B denote bits A through B of the integer X.
+ // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+ // IOW X = (A | B) => U32(X) == A && L32(X) == B
+ //
+ // compute M = val * N (a 96 bit int)
+ // ---------------------------------
+ // tmp2 = U32(val) * N (a 64 bit int)
+ // tmp1 = L32(val) * N (a 64 bit int)
+ // which means
+ // M = val * N = (tmp2 << 32) + tmp1
+ tmp2 = (val >> 32) * N;
+ tmp1 = (val & UINT32_MAX) * N;
+
+ // compute M[32, 95]
+ // tmp2 = tmp2 + U32(tmp1)
+ // = (U32(val) * N) + U32(L32(val) * N)
+ // = M[32, 95]
+ tmp2 += tmp1 >> 32;
+
+ // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+ // an overflow.
+ if ((tmp2 >> 32) >= D) {
+ *res = UINT64_MAX;
+ return false;
+ }
+
+ // Divide. Going in we know
+ // tmp2 = M[32, 95]
+ // U32(tmp2) < D
+ r = tmp2 % D;
+ tmp2 /= D;
+
+ // At this point
+ // tmp1 = L32(val) * N
+ // tmp2 = M[32, 95] / D
+ // = (M / D)[32, 95]
+ // r = M[32, 95] % D
+ // U32(tmp2) = 0
+ //
+ // compute tmp1 = (r | M[0, 31])
+ tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+ // Divide again. Keep the remainder around in order to round properly.
+ r = tmp1 % D;
+ tmp1 /= D;
+
+ // At this point
+ // tmp2 = (M / D)[32, 95]
+ // tmp1 = (M / D)[ 0, 31]
+ // r = M % D
+ // U32(tmp1) = 0
+ // U32(tmp2) = 0
+
+ // Pack the result and deal with the round-up case (As well as the
+ // remote possiblility over overflow in such a case).
+ *res = (tmp2 << 32) | tmp1;
+ if (r && round_up_not_down) {
+ ++(*res);
+ if (!(*res)) {
+ *res = UINT64_MAX;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool linear_transform_s64_to_s64(
+ int64_t val,
+ int64_t basis1,
+ int32_t N,
+ uint32_t D,
+ int64_t basis2,
+ int64_t* out) {
+ uint64_t scaled, res;
+ uint64_t abs_val;
+ bool is_neg;
+
+ if (!out)
+ return false;
+
+ // Compute abs(val - basis_64). Keep track of whether or not this delta
+ // will be negative after the scale opertaion.
+ if (val < basis1) {
+ is_neg = true;
+ abs_val = basis1 - val;
+ } else {
+ is_neg = false;
+ abs_val = val - basis1;
+ }
+
+ if (N < 0)
+ is_neg = !is_neg;
+
+ if (!scale_u64_to_u64(abs_val,
+ ABS(N),
+ D,
+ &scaled,
+ is_neg))
+ return false; // overflow/undeflow
+
+ // if scaled is >= 0x8000<etc>, then we are going to overflow or
+ // underflow unless ABS(basis2) is large enough to pull us back into the
+ // non-overflow/underflow region.
+ if (scaled & INT64_MIN) {
+ if (is_neg && (basis2 < 0))
+ return false; // certain underflow
+
+ if (!is_neg && (basis2 >= 0))
+ return false; // certain overflow
+
+ if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+ return false; // not enough
+
+ // Looks like we are OK
+ *out = (is_neg ? (-scaled) : scaled) + basis2;
+ } else {
+ // Scaled fits within signed bounds, so we just need to check for
+ // over/underflow for two signed integers. Basically, if both scaled
+ // and basis2 have the same sign bit, and the result has a different
+ // sign bit, then we have under/overflow. An easy way to compute this
+ // is
+ // (scaled_signbit XNOR basis_signbit) &&
+ // (scaled_signbit XOR res_signbit)
+ // ==
+ // (scaled_signbit XOR basis_signbit XOR 1) &&
+ // (scaled_signbit XOR res_signbit)
+
+ if (is_neg)
+ scaled = -scaled;
+ res = scaled + basis2;
+
+ if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+ return false;
+
+ *out = res;
+ }
+
+ return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+ if (0 == a_to_b_denom)
+ return false;
+
+ return linear_transform_s64_to_s64(a_in,
+ a_zero,
+ a_to_b_numer,
+ a_to_b_denom,
+ b_zero,
+ b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+ if (0 == a_to_b_numer)
+ return false;
+
+ return linear_transform_s64_to_s64(b_in,
+ b_zero,
+ a_to_b_denom,
+ a_to_b_numer,
+ a_zero,
+ a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+ T a, b;
+ if (!N || !D || !(*D)) {
+ assert(false);
+ return;
+ }
+
+ a = *N;
+ b = *D;
+
+ if (a == 0) {
+ *D = 1;
+ return;
+ }
+
+ // This implements Euclid's method to find GCD.
+ if (a < b) {
+ T tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ while (1) {
+ // a is now the greater of the two.
+ const T remainder = a % b;
+ if (remainder == 0) {
+ *N /= b;
+ *D /= b;
+ return;
+ }
+ // by swapping remainder and b, we are guaranteeing that a is
+ // still the greater of the two upon entrance to the loop.
+ a = b;
+ b = remainder;
+ }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+ if (N && D && *D) {
+ if (*N < 0) {
+ *N = -(*N);
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ *N = -(*N);
+ } else {
+ reduce(reinterpret_cast<uint32_t*>(N), D);
+ }
+ }
+}
+
+} // namespace android
diff --git a/location/java/android/location/Country.java b/location/java/android/location/Country.java
index 3c05403..939bd4a 100755
--- a/location/java/android/location/Country.java
+++ b/location/java/android/location/Country.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Locale;
+
/**
* This class wraps the country information.
*
@@ -74,7 +76,7 @@
|| source > COUNTRY_SOURCE_LOCALE) {
throw new IllegalArgumentException();
}
- mCountryIso = countryIso.toLowerCase();
+ mCountryIso = countryIso.toUpperCase(Locale.US);
mSource = source;
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 2557730..33312d1 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1568,7 +1568,14 @@
return;
case MEDIA_TIMED_TEXT:
if (mOnTimedTextListener != null) {
- mOnTimedTextListener.onTimedText(mMediaPlayer, (String)msg.obj);
+ if (msg.obj == null) {
+ mOnTimedTextListener.onTimedText(mMediaPlayer, null);
+ } else {
+ if (msg.obj instanceof byte[]) {
+ TimedText text = new TimedText((byte[])(msg.obj));
+ mOnTimedTextListener.onTimedText(mMediaPlayer, text);
+ }
+ }
}
return;
@@ -1755,14 +1762,14 @@
public interface OnTimedTextListener
{
/**
- * Called to indicate the video size
+ * Called to indicate an avaliable timed text
*
* @param mp the MediaPlayer associated with this callback
- * @param text the timed text sample which contains the
- * text needed to be displayed.
+ * @param text the timed text sample which contains the text
+ * needed to be displayed and the display format.
* {@hide}
*/
- public void onTimedText(MediaPlayer mp, String text);
+ public void onTimedText(MediaPlayer mp, TimedText text);
}
/**
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index dd45111..e3cbd57 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,17 +16,16 @@
package android.media;
-import android.media.CamcorderProfile;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Surface;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
+
import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.lang.ref.WeakReference;
/**
@@ -112,7 +111,8 @@
/**
* Sets a Camera to use for recording. Use this function to switch
* quickly between preview and capture mode without a teardown of
- * the camera object. Must call before prepare().
+ * the camera object. {@link android.hardware.Camera#unlock()} should be
+ * called before this. Must call before prepare().
*
* @param c the Camera to use for recording
*/
@@ -718,6 +718,12 @@
* Begins capturing and encoding data to the file specified with
* setOutputFile(). Call this after prepare().
*
+ * <p>Since API level 13, if applications set a camera via
+ * {@link #setCamera(Camera)}, the apps can use the camera after this method
+ * call. The apps do not need to lock the camera again. However, if this
+ * method fails, the apps should still lock the camera back. The apps should
+ * not start another recording session during recording.
+ *
* @throws IllegalStateException if it is called before
* prepare().
*/
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 8d408c2..591a8b9 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -32,17 +32,13 @@
Class to hold the media's metadata. Metadata are used
for human consumption and can be embedded in the media (e.g
shoutcast) or available from an external source. The source can be
- local (e.g thumbnail stored in the DB) or remote (e.g caption
- server).
+ local (e.g thumbnail stored in the DB) or remote.
Metadata is like a Bundle. It is sparse and each key can occur at
most once. The key is an integer and the value is the actual metadata.
The caller is expected to know the type of the metadata and call
the right get* method to fetch its value.
-
- // FIXME: unhide.
- {@hide}
*/
public class Metadata
{
@@ -59,69 +55,190 @@
// client to make the data purge-able once it is done with it.
//
+ /**
+ * {@hide}
+ */
public static final int ANY = 0; // Never used for metadata returned, only for filtering.
// Keep in sync with kAny in MediaPlayerService.cpp
+ // Playback capabilities.
+ /**
+ * Indicate whether the media can be paused
+ */
+ public static final int PAUSE_AVAILABLE = 1; // Boolean
+ /**
+ * Indicate whether the media can be backward seeked
+ */
+ public static final int SEEK_BACKWARD_AVAILABLE = 2; // Boolean
+ /**
+ * Indicate whether the media can be forward seeked
+ */
+ public static final int SEEK_FORWARD_AVAILABLE = 3; // Boolean
+ /**
+ * Indicate whether the media can be seeked
+ */
+ public static final int SEEK_AVAILABLE = 4; // Boolean
+
// TODO: Should we use numbers compatible with the metadata retriever?
- public static final int TITLE = 1; // String
- public static final int COMMENT = 2; // String
- public static final int COPYRIGHT = 3; // String
- public static final int ALBUM = 4; // String
- public static final int ARTIST = 5; // String
- public static final int AUTHOR = 6; // String
- public static final int COMPOSER = 7; // String
- public static final int GENRE = 8; // String
- public static final int DATE = 9; // Date
- public static final int DURATION = 10; // Integer(millisec)
- public static final int CD_TRACK_NUM = 11; // Integer 1-based
- public static final int CD_TRACK_MAX = 12; // Integer
- public static final int RATING = 13; // String
- public static final int ALBUM_ART = 14; // byte[]
- public static final int VIDEO_FRAME = 15; // Bitmap
- public static final int CAPTION = 16; // TimedText
+ /**
+ * {@hide}
+ */
+ public static final int TITLE = 5; // String
+ /**
+ * {@hide}
+ */
+ public static final int COMMENT = 6; // String
+ /**
+ * {@hide}
+ */
+ public static final int COPYRIGHT = 7; // String
+ /**
+ * {@hide}
+ */
+ public static final int ALBUM = 8; // String
+ /**
+ * {@hide}
+ */
+ public static final int ARTIST = 9; // String
+ /**
+ * {@hide}
+ */
+ public static final int AUTHOR = 10; // String
+ /**
+ * {@hide}
+ */
+ public static final int COMPOSER = 11; // String
+ /**
+ * {@hide}
+ */
+ public static final int GENRE = 12; // String
+ /**
+ * {@hide}
+ */
+ public static final int DATE = 13; // Date
+ /**
+ * {@hide}
+ */
+ public static final int DURATION = 14; // Integer(millisec)
+ /**
+ * {@hide}
+ */
+ public static final int CD_TRACK_NUM = 15; // Integer 1-based
+ /**
+ * {@hide}
+ */
+ public static final int CD_TRACK_MAX = 16; // Integer
+ /**
+ * {@hide}
+ */
+ public static final int RATING = 17; // String
+ /**
+ * {@hide}
+ */
+ public static final int ALBUM_ART = 18; // byte[]
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_FRAME = 19; // Bitmap
- public static final int BIT_RATE = 17; // Integer, Aggregate rate of
- // all the streams in bps.
+ /**
+ * {@hide}
+ */
+ public static final int BIT_RATE = 20; // Integer, Aggregate rate of
+ // all the streams in bps.
- public static final int AUDIO_BIT_RATE = 18; // Integer, bps
- public static final int VIDEO_BIT_RATE = 19; // Integer, bps
- public static final int AUDIO_SAMPLE_RATE = 20; // Integer, Hz
- public static final int VIDEO_FRAME_RATE = 21; // Integer, Hz
+ /**
+ * {@hide}
+ */
+ public static final int AUDIO_BIT_RATE = 21; // Integer, bps
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_BIT_RATE = 22; // Integer, bps
+ /**
+ * {@hide}
+ */
+ public static final int AUDIO_SAMPLE_RATE = 23; // Integer, Hz
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_FRAME_RATE = 24; // Integer, Hz
// See RFC2046 and RFC4281.
- public static final int MIME_TYPE = 22; // String
- public static final int AUDIO_CODEC = 23; // String
- public static final int VIDEO_CODEC = 24; // String
+ /**
+ * {@hide}
+ */
+ public static final int MIME_TYPE = 25; // String
+ /**
+ * {@hide}
+ */
+ public static final int AUDIO_CODEC = 26; // String
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_CODEC = 27; // String
- public static final int VIDEO_HEIGHT = 25; // Integer
- public static final int VIDEO_WIDTH = 26; // Integer
- public static final int NUM_TRACKS = 27; // Integer
- public static final int DRM_CRIPPLED = 28; // Boolean
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_HEIGHT = 28; // Integer
+ /**
+ * {@hide}
+ */
+ public static final int VIDEO_WIDTH = 29; // Integer
+ /**
+ * {@hide}
+ */
+ public static final int NUM_TRACKS = 30; // Integer
+ /**
+ * {@hide}
+ */
+ public static final int DRM_CRIPPLED = 31; // Boolean
- // Playback capabilities.
- public static final int PAUSE_AVAILABLE = 29; // Boolean
- public static final int SEEK_BACKWARD_AVAILABLE = 30; // Boolean
- public static final int SEEK_FORWARD_AVAILABLE = 31; // Boolean
- public static final int SEEK_AVAILABLE = 32; // Boolean
-
- private static final int LAST_SYSTEM = 32;
+ private static final int LAST_SYSTEM = 31;
private static final int FIRST_CUSTOM = 8192;
// Shorthands to set the MediaPlayer's metadata filter.
+ /**
+ * {@hide}
+ */
public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
+ /**
+ * {@hide}
+ */
public static final Set<Integer> MATCH_ALL = Collections.singleton(ANY);
+ /**
+ * {@hide}
+ */
public static final int STRING_VAL = 1;
+ /**
+ * {@hide}
+ */
public static final int INTEGER_VAL = 2;
+ /**
+ * {@hide}
+ */
public static final int BOOLEAN_VAL = 3;
+ /**
+ * {@hide}
+ */
public static final int LONG_VAL = 4;
+ /**
+ * {@hide}
+ */
public static final int DOUBLE_VAL = 5;
- public static final int TIMED_TEXT_VAL = 6;
- public static final int DATE_VAL = 7;
- public static final int BYTE_ARRAY_VAL = 8;
+ /**
+ * {@hide}
+ */
+ public static final int DATE_VAL = 6;
+ /**
+ * {@hide}
+ */
+ public static final int BYTE_ARRAY_VAL = 7;
// FIXME: misses a type for shared heap is missing (MemoryFile).
// FIXME: misses a type for bitmaps.
- private static final int LAST_TYPE = 8;
+ private static final int LAST_TYPE = 7;
private static final String TAG = "media.Metadata";
private static final int kInt32Size = 4;
@@ -142,28 +259,8 @@
new HashMap<Integer, Integer>();
/**
- * Helper class to hold a triple (time, duration, text). Can be used to
- * implement caption.
+ * {@hide}
*/
- public class TimedText {
- private Date mTime;
- private int mDuration; // millisec
- private String mText;
-
- public TimedText(Date time, int duration, String text) {
- mTime = time;
- mDuration = duration;
- mText = text;
- }
-
- public String toString() {
- StringBuilder res = new StringBuilder(80);
- res.append(mTime).append("-").append(mDuration)
- .append(":").append(mText);
- return res.toString();
- }
- }
-
public Metadata() { }
/**
@@ -273,6 +370,7 @@
* should not modify the parcel after this call (and
* not call recycle on it.)
* @return false if an error occurred.
+ * {@hide}
*/
public boolean parse(Parcel parcel) {
if (parcel.dataAvail() < kMetaHeaderSize) {
@@ -328,36 +426,59 @@
// Caller must make sure the key is present using the {@code has}
// method otherwise a RuntimeException will occur.
+ /**
+ * {@hide}
+ */
public String getString(final int key) {
checkType(key, STRING_VAL);
return mParcel.readString();
}
+ /**
+ * {@hide}
+ */
public int getInt(final int key) {
checkType(key, INTEGER_VAL);
return mParcel.readInt();
}
+ /**
+ * Get the boolean value indicated by key
+ */
public boolean getBoolean(final int key) {
checkType(key, BOOLEAN_VAL);
return mParcel.readInt() == 1;
}
+ /**
+ * {@hide}
+ */
public long getLong(final int key) {
- checkType(key, LONG_VAL);
+ checkType(key, LONG_VAL); /**
+ * {@hide}
+ */
return mParcel.readLong();
}
+ /**
+ * {@hide}
+ */
public double getDouble(final int key) {
checkType(key, DOUBLE_VAL);
return mParcel.readDouble();
}
+ /**
+ * {@hide}
+ */
public byte[] getByteArray(final int key) {
checkType(key, BYTE_ARRAY_VAL);
return mParcel.createByteArray();
}
+ /**
+ * {@hide}
+ */
public Date getDate(final int key) {
checkType(key, DATE_VAL);
final long timeSinceEpoch = mParcel.readLong();
@@ -374,29 +495,30 @@
}
}
- public TimedText getTimedText(final int key) {
- checkType(key, TIMED_TEXT_VAL);
- final Date startTime = new Date(mParcel.readLong()); // epoch
- final int duration = mParcel.readInt(); // millisec
-
- return new TimedText(startTime,
- duration,
- mParcel.readString());
- }
-
- // @return the last available system metadata id. Ids are
- // 1-indexed.
+ /**
+ * @return the last available system metadata id. Ids are
+ * 1-indexed.
+ * {@hide}
+ */
public static int lastSytemId() { return LAST_SYSTEM; }
- // @return the first available cutom metadata id.
+ /**
+ * @return the first available cutom metadata id.
+ * {@hide}
+ */
public static int firstCustomId() { return FIRST_CUSTOM; }
- // @return the last value of known type. Types are 1-indexed.
+ /**
+ * @return the last value of known type. Types are 1-indexed.
+ * {@hide}
+ */
public static int lastType() { return LAST_TYPE; }
- // Check val is either a system id or a custom one.
- // @param val Metadata key to test.
- // @return true if it is in a valid range.
+ /**
+ * Check val is either a system id or a custom one.
+ * @param val Metadata key to test.
+ * @return true if it is in a valid range.
+ **/
private boolean checkMetadataId(final int val) {
if (val <= ANY || (LAST_SYSTEM < val && val < FIRST_CUSTOM)) {
Log.e(TAG, "Invalid metadata ID " + val);
@@ -405,7 +527,9 @@
return true;
}
- // Check the type of the data match what is expected.
+ /**
+ * Check the type of the data match what is expected.
+ */
private void checkType(final int key, final int expectedType) {
final int pos = mKeyToPosMap.get(key);
diff --git a/media/java/android/media/TimedText.java b/media/java/android/media/TimedText.java
new file mode 100644
index 0000000..a055c8b
--- /dev/null
+++ b/media/java/android/media/TimedText.java
@@ -0,0 +1,655 @@
+/*
+ * 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 android.media;
+
+import android.os.Parcel;
+import android.util.Log;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Class to hold the timed text's metadata.
+ *
+ * {@hide}
+ */
+public class TimedText
+{
+ private static final int FIRST_PUBLIC_KEY = 1;
+
+ // These keys must be in sync with the keys in TextDescription.h
+ public static final int KEY_DISPLAY_FLAGS = 1; // int
+ public static final int KEY_STYLE_FLAGS = 2; // int
+ public static final int KEY_BACKGROUND_COLOR_RGBA = 3; // int
+ public static final int KEY_HIGHLIGHT_COLOR_RGBA = 4; // int
+ public static final int KEY_SCROLL_DELAY = 5; // int
+ public static final int KEY_WRAP_TEXT = 6; // int
+ public static final int KEY_START_TIME = 7; // int
+ public static final int KEY_STRUCT_BLINKING_TEXT_LIST = 8; // List<CharPos>
+ public static final int KEY_STRUCT_FONT_LIST = 9; // List<Font>
+ public static final int KEY_STRUCT_HIGHLIGHT_LIST = 10; // List<CharPos>
+ public static final int KEY_STRUCT_HYPER_TEXT_LIST = 11; // List<HyperText>
+ public static final int KEY_STRUCT_KARAOKE_LIST = 12; // List<Karaoke>
+ public static final int KEY_STRUCT_STYLE_LIST = 13; // List<Style>
+ public static final int KEY_STRUCT_TEXT_POS = 14; // TextPos
+ public static final int KEY_STRUCT_JUSTIFICATION = 15; // Justification
+ public static final int KEY_STRUCT_TEXT = 16; // Text
+
+ private static final int LAST_PUBLIC_KEY = 16;
+
+ private static final int FIRST_PRIVATE_KEY = 101;
+
+ // The following keys are used between TimedText.java and
+ // TextDescription.cpp in order to parce the Parcel.
+ private static final int KEY_GLOBAL_SETTING = 101;
+ private static final int KEY_LOCAL_SETTING = 102;
+ private static final int KEY_START_CHAR = 103;
+ private static final int KEY_END_CHAR = 104;
+ private static final int KEY_FONT_ID = 105;
+ private static final int KEY_FONT_SIZE = 106;
+ private static final int KEY_TEXT_COLOR_RGBA = 107;
+
+ private static final int LAST_PRIVATE_KEY = 107;
+
+ private static final String TAG = "TimedText";
+
+ private Parcel mParcel = Parcel.obtain();
+ private final HashMap<Integer, Object> mKeyObjectMap =
+ new HashMap<Integer, Object>();
+
+ private int mDisplayFlags = -1;
+ private int mBackgroundColorRGBA = -1;
+ private int mHighlightColorRGBA = -1;
+ private int mScrollDelay = -1;
+ private int mWrapText = -1;
+
+ private List<CharPos> mBlinkingPosList = null;
+ private List<CharPos> mHighlightPosList = null;
+ private List<Karaoke> mKaraokeList = null;
+ private List<Font> mFontList = null;
+ private List<Style> mStyleList = null;
+ private List<HyperText> mHyperTextList = null;
+
+ private TextPos mTextPos;
+ private Justification mJustification;
+ private Text mTextStruct;
+
+ /**
+ * Helper class to hold the text length and text content of
+ * one text sample. The member variables in this class are
+ * read-only.
+ */
+ public class Text {
+ /**
+ * The byte-count of this text sample
+ */
+ public int textLen;
+
+ /**
+ * The text sample
+ */
+ public byte[] text;
+
+ public Text() { }
+ }
+
+ /**
+ * Helper class to hold the start char offset and end char offset
+ * for Blinking Text or Highlight Text. endChar is the end offset
+ * of the text (startChar + number of characters to be highlighted
+ * or blinked). The member variables in this class are read-only.
+ */
+ public class CharPos {
+ /**
+ * The offset of the start character
+ */
+ public int startChar = -1;
+
+ /**
+ * The offset of the end character
+ */
+ public int endChar = -1;
+
+ public CharPos() { }
+ }
+
+ /**
+ * Helper class to hold the box position to display the text sample.
+ * The member variables in this class are read-only.
+ */
+ public class TextPos {
+ /**
+ * The top position of the text
+ */
+ public int top = -1;
+
+ /**
+ * The left position of the text
+ */
+ public int left = -1;
+
+ /**
+ * The bottom position of the text
+ */
+ public int bottom = -1;
+
+ /**
+ * The right position of the text
+ */
+ public int right = -1;
+
+ public TextPos() { }
+ }
+
+ /**
+ * Helper class to hold the justification for text display in the text box.
+ * The member variables in this class are read-only.
+ */
+ public class Justification {
+ /**
+ * horizontalJustification 0: left, 1: centered, -1: right
+ */
+ public int horizontalJustification = -1;
+
+ /**
+ * verticalJustification 0: top, 1: centered, -1: bottom
+ */
+ public int verticalJustification = -1;
+
+ public Justification() { }
+ }
+
+ /**
+ * Helper class to hold the style information to display the text.
+ * The member variables in this class are read-only.
+ */
+ public class Style {
+ /**
+ * The offset of the start character which applys this style
+ */
+ public int startChar = -1;
+
+ /**
+ * The offset of the end character which applys this style
+ */
+ public int endChar = -1;
+
+ /**
+ * ID of the font. This ID will be used to choose the font
+ * to be used from the font list.
+ */
+ public int fontID = -1;
+
+ /**
+ * True if the characters should be bold
+ */
+ public boolean isBold = false;
+
+ /**
+ * True if the characters should be italic
+ */
+ public boolean isItalic = false;
+
+ /**
+ * True if the characters should be underlined
+ */
+ public boolean isUnderlined = false;
+
+ /**
+ * The size of the font
+ */
+ public int fontSize = -1;
+
+ /**
+ * To specify the RGBA color: 8 bits each of red, green, blue,
+ * and an alpha(transparency) value
+ */
+ public int colorRGBA = -1;
+
+ public Style() { }
+ }
+
+ /**
+ * Helper class to hold the font ID and name.
+ * The member variables in this class are read-only.
+ */
+ public class Font {
+ /**
+ * The font ID
+ */
+ public int ID = -1;
+
+ /**
+ * The font name
+ */
+ public String name;
+
+ public Font() { }
+ }
+
+ /**
+ * Helper class to hold the karaoke information.
+ * The member variables in this class are read-only.
+ */
+ public class Karaoke {
+ /**
+ * The start time (in milliseconds) to highlight the characters
+ * specified by startChar and endChar.
+ */
+ public int startTimeMs = -1;
+
+ /**
+ * The end time (in milliseconds) to highlight the characters
+ * specified by startChar and endChar.
+ */
+ public int endTimeMs = -1;
+
+ /**
+ * The offset of the start character to be highlighted
+ */
+ public int startChar = -1;
+
+ /**
+ * The offset of the end character to be highlighted
+ */
+ public int endChar = -1;
+
+ public Karaoke() { }
+ }
+
+ /**
+ * Helper class to hold the hyper text information.
+ * The member variables in this class are read-only.
+ */
+ public class HyperText {
+ /**
+ * The offset of the start character
+ */
+ public int startChar = -1;
+
+ /**
+ * The offset of the end character
+ */
+ public int endChar = -1;
+
+ /**
+ * The linked-to URL
+ */
+ public String URL;
+
+ /**
+ * The "alt" string for user display
+ */
+ public String altString;
+
+ public HyperText() { }
+ }
+
+ /**
+ * @param obj the byte array which contains the timed text.
+ * @throws IllegalArgumentExcept if parseParcel() fails.
+ * {@hide}
+ */
+ public TimedText(byte[] obj) {
+ mParcel.unmarshall(obj, 0, obj.length);
+
+ if (!parseParcel()) {
+ mKeyObjectMap.clear();
+ throw new IllegalArgumentException("parseParcel() fails");
+ }
+ }
+
+ /**
+ * Go over all the records, collecting metadata keys and fields in the
+ * Parcel. These are stored in mKeyObjectMap for application to retrieve.
+ * @return false if an error occurred during parsing. Otherwise, true.
+ */
+ private boolean parseParcel() {
+ mParcel.setDataPosition(0);
+ if (mParcel.dataAvail() == 0) {
+ return false;
+ }
+
+ int type = mParcel.readInt();
+ if (type == KEY_LOCAL_SETTING) {
+ type = mParcel.readInt();
+ if (type != KEY_START_TIME) {
+ return false;
+ }
+ int mStartTimeMs = mParcel.readInt();
+ mKeyObjectMap.put(type, mStartTimeMs);
+
+ type = mParcel.readInt();
+ if (type != KEY_STRUCT_TEXT) {
+ return false;
+ }
+
+ mTextStruct = new Text();
+ mTextStruct.textLen = mParcel.readInt();
+
+ mTextStruct.text = mParcel.createByteArray();
+ mKeyObjectMap.put(type, mTextStruct);
+
+ } else if (type != KEY_GLOBAL_SETTING) {
+ Log.w(TAG, "Invalid timed text key found: " + type);
+ return false;
+ }
+
+ while (mParcel.dataAvail() > 0) {
+ int key = mParcel.readInt();
+ if (!isValidKey(key)) {
+ Log.w(TAG, "Invalid timed text key found: " + key);
+ return false;
+ }
+
+ Object object = null;
+
+ switch (key) {
+ case KEY_STRUCT_STYLE_LIST: {
+ readStyle();
+ object = mStyleList;
+ break;
+ }
+ case KEY_STRUCT_FONT_LIST: {
+ readFont();
+ object = mFontList;
+ break;
+ }
+ case KEY_STRUCT_HIGHLIGHT_LIST: {
+ readHighlight();
+ object = mHighlightPosList;
+ break;
+ }
+ case KEY_STRUCT_KARAOKE_LIST: {
+ readKaraoke();
+ object = mKaraokeList;
+ break;
+ }
+ case KEY_STRUCT_HYPER_TEXT_LIST: {
+ readHyperText();
+ object = mHyperTextList;
+
+ break;
+ }
+ case KEY_STRUCT_BLINKING_TEXT_LIST: {
+ readBlinkingText();
+ object = mBlinkingPosList;
+
+ break;
+ }
+ case KEY_WRAP_TEXT: {
+ mWrapText = mParcel.readInt();
+ object = mWrapText;
+ break;
+ }
+ case KEY_HIGHLIGHT_COLOR_RGBA: {
+ mHighlightColorRGBA = mParcel.readInt();
+ object = mHighlightColorRGBA;
+ break;
+ }
+ case KEY_DISPLAY_FLAGS: {
+ mDisplayFlags = mParcel.readInt();
+ object = mDisplayFlags;
+ break;
+ }
+ case KEY_STRUCT_JUSTIFICATION: {
+ mJustification = new Justification();
+
+ mJustification.horizontalJustification = mParcel.readInt();
+ mJustification.verticalJustification = mParcel.readInt();
+
+ object = mJustification;
+ break;
+ }
+ case KEY_BACKGROUND_COLOR_RGBA: {
+ mBackgroundColorRGBA = mParcel.readInt();
+ object = mBackgroundColorRGBA;
+ break;
+ }
+ case KEY_STRUCT_TEXT_POS: {
+ mTextPos = new TextPos();
+
+ mTextPos.top = mParcel.readInt();
+ mTextPos.left = mParcel.readInt();
+ mTextPos.bottom = mParcel.readInt();
+ mTextPos.right = mParcel.readInt();
+
+ object = mTextPos;
+ break;
+ }
+ case KEY_SCROLL_DELAY: {
+ mScrollDelay = mParcel.readInt();
+ object = mScrollDelay;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ if (object != null) {
+ if (mKeyObjectMap.containsKey(key)) {
+ mKeyObjectMap.remove(key);
+ }
+ mKeyObjectMap.put(key, object);
+ }
+ }
+
+ mParcel.recycle();
+ return true;
+ }
+
+ /**
+ * To parse and store the Style list.
+ */
+ private void readStyle() {
+ Style style = new Style();
+ boolean endOfStyle = false;
+
+ while (!endOfStyle && (mParcel.dataAvail() > 0)) {
+ int key = mParcel.readInt();
+ switch (key) {
+ case KEY_START_CHAR: {
+ style.startChar = mParcel.readInt();
+ break;
+ }
+ case KEY_END_CHAR: {
+ style.endChar = mParcel.readInt();
+ break;
+ }
+ case KEY_FONT_ID: {
+ style.fontID = mParcel.readInt();
+ break;
+ }
+ case KEY_STYLE_FLAGS: {
+ int flags = mParcel.readInt();
+ // In the absence of any bits set in flags, the text
+ // is plain. Otherwise, 1: bold, 2: italic, 4: underline
+ style.isBold = ((flags % 2) == 1);
+ style.isItalic = ((flags % 4) >= 2);
+ style.isUnderlined = ((flags / 4) == 1);
+ break;
+ }
+ case KEY_FONT_SIZE: {
+ style.fontSize = mParcel.readInt();
+ break;
+ }
+ case KEY_TEXT_COLOR_RGBA: {
+ style.colorRGBA = mParcel.readInt();
+ break;
+ }
+ default: {
+ // End of the Style parsing. Reset the data position back
+ // to the position before the last mParcel.readInt() call.
+ mParcel.setDataPosition(mParcel.dataPosition() - 4);
+ endOfStyle = true;
+ break;
+ }
+ }
+ }
+
+ if (mStyleList == null) {
+ mStyleList = new ArrayList<Style>();
+ }
+ mStyleList.add(style);
+ }
+
+ /**
+ * To parse and store the Font list
+ */
+ private void readFont() {
+ int entryCount = mParcel.readInt();
+
+ for (int i = 0; i < entryCount; i++) {
+ Font font = new Font();
+
+ font.ID = mParcel.readInt();
+ int nameLen = mParcel.readInt();
+
+ byte[] text = mParcel.createByteArray();
+ font.name = new String(text, 0, nameLen);
+
+ if (mFontList == null) {
+ mFontList = new ArrayList<Font>();
+ }
+ mFontList.add(font);
+ }
+ }
+
+ /**
+ * To parse and store the Highlight list
+ */
+ private void readHighlight() {
+ CharPos pos = new CharPos();
+
+ pos.startChar = mParcel.readInt();
+ pos.endChar = mParcel.readInt();
+
+ if (mHighlightPosList == null) {
+ mHighlightPosList = new ArrayList<CharPos>();
+ }
+ mHighlightPosList.add(pos);
+ }
+
+ /**
+ * To parse and store the Karaoke list
+ */
+ private void readKaraoke() {
+ int entryCount = mParcel.readInt();
+
+ for (int i = 0; i < entryCount; i++) {
+ Karaoke kara = new Karaoke();
+
+ kara.startTimeMs = mParcel.readInt();
+ kara.endTimeMs = mParcel.readInt();
+ kara.startChar = mParcel.readInt();
+ kara.endChar = mParcel.readInt();
+
+ if (mKaraokeList == null) {
+ mKaraokeList = new ArrayList<Karaoke>();
+ }
+ mKaraokeList.add(kara);
+ }
+ }
+
+ /**
+ * To parse and store HyperText list
+ */
+ private void readHyperText() {
+ HyperText hyperText = new HyperText();
+
+ hyperText.startChar = mParcel.readInt();
+ hyperText.endChar = mParcel.readInt();
+
+ int len = mParcel.readInt();
+ byte[] url = mParcel.createByteArray();
+ hyperText.URL = new String(url, 0, len);
+
+ len = mParcel.readInt();
+ byte[] alt = mParcel.createByteArray();
+ hyperText.altString = new String(alt, 0, len);
+
+ if (mHyperTextList == null) {
+ mHyperTextList = new ArrayList<HyperText>();
+ }
+ mHyperTextList.add(hyperText);
+ }
+
+ /**
+ * To parse and store blinking text list
+ */
+ private void readBlinkingText() {
+ CharPos blinkingPos = new CharPos();
+
+ blinkingPos.startChar = mParcel.readInt();
+ blinkingPos.endChar = mParcel.readInt();
+
+ if (mBlinkingPosList == null) {
+ mBlinkingPosList = new ArrayList<CharPos>();
+ }
+ mBlinkingPosList.add(blinkingPos);
+ }
+
+ /**
+ * To check whether the given key is valid.
+ * @param key the key to be checked.
+ * @return true if the key is a valid one. Otherwise, false.
+ */
+ public boolean isValidKey(final int key) {
+ if (!((key >= FIRST_PUBLIC_KEY) && (key <= LAST_PUBLIC_KEY))
+ && !((key >= FIRST_PRIVATE_KEY) && (key <= LAST_PRIVATE_KEY))) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * To check whether the given key is contained in this TimedText object.
+ * @param key the key to be checked.
+ * @return true if the key is contained in this TimedText object.
+ * Otherwise, false.
+ */
+ public boolean containsKey(final int key) {
+ if (isValidKey(key) && mKeyObjectMap.containsKey(key)) {
+ return true;
+ }
+ return false;
+ }
+ /**
+ * @return a set of the keys contained in this TimedText object.
+ */
+ public Set keySet() {
+ return mKeyObjectMap.keySet();
+ }
+
+ /**
+ * To retrieve the object associated with the key. Caller must make sure
+ * the key is present using the containsKey method otherwise a
+ * RuntimeException will occur.
+ * @param key the key used to retrieve the object.
+ * @return an object. The object could be an instanceof Integer, List, or
+ * any of the helper classes such as TextPos, Justification, and Text.
+ */
+ public Object getObject(final int key) {
+ if (containsKey(key)) {
+ return mKeyObjectMap.get(key);
+ } else {
+ throw new IllegalArgumentException("Invalid key: " + key);
+ }
+ }
+}
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 29c4b89..0d2bcd5 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -957,12 +957,8 @@
public static final int FADE_FROM_BLACK = 8;
- public static final int CURTAIN_OPENING = 9;
-
public static final int FADE_TO_BLACK = 16;
- public static final int CURTAIN_CLOSING = 17;
-
public static final int EXTERNAL = 256;
public static final int BLACK_AND_WHITE = 257;
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 2105deb..649b98a 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -38,6 +38,7 @@
import android.graphics.Rect;
import android.media.videoeditor.MediaImageItem;
import android.media.videoeditor.MediaItem;
+import android.media.MediaMetadataRetriever;
import android.util.Log;
import android.util.Xml;
import android.view.Surface;
@@ -1833,12 +1834,32 @@
}
Bitmap projectBitmap = null;
- try {
- projectBitmap = mI.getThumbnail(width, height, 500);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException ("Illegal argument error creating project thumbnail");
- } catch (IOException e) {
- throw new IllegalArgumentException ("IO Error creating project thumbnail");
+ String filename = mI.getFilename();
+ if (mI instanceof MediaVideoItem) {
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ retriever.setDataSource(filename);
+ Bitmap bitmap = retriever.getFrameAtTime();
+ retriever.release();
+ retriever = null;
+ if (bitmap == null) {
+ String msg = "Thumbnail extraction from " +
+ filename + " failed";
+ throw new IllegalArgumentException(msg);
+ }
+ // Resize the thumbnail to the target size
+ projectBitmap =
+ Bitmap.createScaledBitmap(bitmap, width, height, true);
+ } else {
+ try {
+ projectBitmap = mI.getThumbnail(width, height, 500);
+ } catch (IllegalArgumentException e) {
+ String msg = "Project thumbnail extraction from " +
+ filename + " failed";
+ throw new IllegalArgumentException(msg);
+ } catch (IOException e) {
+ String msg = "IO Error creating project thumbnail";
+ throw new IllegalArgumentException(msg);
+ }
}
try {
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index c9e0f6f..4e271c7 100644
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -92,13 +92,18 @@
};
private static final String ID_WHERE = Files.FileColumns._ID + "=?";
private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
- private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
- private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
+
+ private static final String STORAGE_WHERE = Files.FileColumns.STORAGE_ID + "=?";
+ private static final String FORMAT_WHERE = Files.FileColumns.PARENT + "=?";
+ private static final String PARENT_WHERE = Files.FileColumns.FORMAT + "=?";
+ private static final String STORAGE_FORMAT_WHERE = STORAGE_WHERE + " AND "
+ Files.FileColumns.FORMAT + "=?";
- private static final String PARENT_STORAGE_WHERE = PARENT_WHERE + " AND "
- + Files.FileColumns.STORAGE_ID + "=?";
- private static final String PARENT_STORAGE_FORMAT_WHERE = PARENT_STORAGE_WHERE + " AND "
- + Files.FileColumns.FORMAT + "=?";
+ private static final String STORAGE_PARENT_WHERE = STORAGE_WHERE + " AND "
+ + Files.FileColumns.PARENT + "=?";
+ private static final String FORMAT_PARENT_WHERE = FORMAT_WHERE + " AND "
+ + Files.FileColumns.PARENT + "=?";
+ private static final String STORAGE_FORMAT_PARENT_WHERE = STORAGE_FORMAT_WHERE + " AND "
+ + Files.FileColumns.PARENT + "=?";
private final MediaScanner mMediaScanner;
@@ -249,26 +254,67 @@
}
private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException {
- if (storageID != 0) {
- if (format != 0) {
- return mMediaProvider.query(mObjectsUri, ID_PROJECTION,
- PARENT_STORAGE_FORMAT_WHERE,
- new String[] { Integer.toString(parent), Integer.toString(storageID),
- Integer.toString(format) }, null);
+ if (storageID == 0xFFFFFFFF) {
+ // query all stores
+ if (format == 0) {
+ // query all formats
+ if (parent == 0) {
+ // query all objects
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null);
+ }
+ if (parent == 0xFFFFFFFF) {
+ // all objects in root of store
+ parent = 0;
+ }
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE,
+ new String[] { Integer.toString(parent) }, null);
} else {
- return mMediaProvider.query(mObjectsUri, ID_PROJECTION,
- PARENT_STORAGE_WHERE, new String[]
- { Integer.toString(parent), Integer.toString(storageID) }, null);
+ // query specific format
+ if (parent == 0) {
+ // query all objects
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE,
+ new String[] { Integer.toString(format) }, null);
+ }
+ if (parent == 0xFFFFFFFF) {
+ // all objects in root of store
+ parent = 0;
+ }
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE,
+ new String[] { Integer.toString(format), Integer.toString(parent) }, null);
}
} else {
- if (format != 0) {
- return mMediaProvider.query(mObjectsUri, ID_PROJECTION,
- PARENT_FORMAT_WHERE,
- new String[] { Integer.toString(parent), Integer.toString(format) },
- null);
+ // query specific store
+ if (format == 0) {
+ // query all formats
+ if (parent == 0) {
+ // query all objects
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE,
+ new String[] { Integer.toString(storageID) }, null);
+ }
+ if (parent == 0xFFFFFFFF) {
+ // all objects in root of store
+ parent = 0;
+ }
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE,
+ new String[] { Integer.toString(storageID), Integer.toString(parent) },
+ null);
} else {
- return mMediaProvider.query(mObjectsUri, ID_PROJECTION,
- PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
+ // query specific format
+ if (parent == 0) {
+ // query all objects
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE,
+ new String[] { Integer.toString(storageID), Integer.toString(format) },
+ null);
+ }
+ if (parent == 0xFFFFFFFF) {
+ // all objects in root of store
+ parent = 0;
+ }
+ return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE,
+ new String[] { Integer.toString(storageID),
+ Integer.toString(format),
+ Integer.toString(parent) },
+ null);
}
}
}
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 687cc44..0133cf6 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -33,8 +33,8 @@
System.loadLibrary("media_jni");
}
- public MtpServer(MtpDatabase database) {
- native_setup(database);
+ public MtpServer(MtpDatabase database, boolean usePtp) {
+ native_setup(database, usePtp);
}
public void start() {
@@ -69,7 +69,7 @@
native_remove_storage(storage.getStorageId());
}
- private native final void native_setup(MtpDatabase database);
+ private native final void native_setup(MtpDatabase database, boolean usePtp);
private native final void native_start();
private native final void native_stop();
private native final void native_send_object_added(int handle);
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 2f7d7ee..12391c8 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -158,7 +158,7 @@
}
sp<Camera> c = get_native_camera(env, camera, NULL);
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
- process_media_recorder_call(env, mr->setCamera(c->remote()),
+ process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),
"java/lang/RuntimeException", "setCamera failed.");
}
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index e36e6db..aaf85c3 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -68,13 +68,15 @@
class MtpThread : public Thread {
private:
MtpDatabase* mDatabase;
+ bool mPtp;
MtpServer* mServer;
MtpStorageList mStorageList;
int mFd;
public:
- MtpThread(MtpDatabase* database)
+ MtpThread(MtpDatabase* database, bool usePtp)
: mDatabase(database),
+ mPtp(usePtp),
mServer(NULL),
mFd(-1)
{
@@ -113,7 +115,7 @@
mFd = open("/dev/mtp_usb", O_RDWR);
if (mFd >= 0) {
- mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775);
+ mServer = new MtpServer(mFd, mDatabase, mPtp, AID_MEDIA_RW, 0664, 0775);
for (size_t i = 0; i < mStorageList.size(); i++) {
mServer->addStorage(mStorageList[i]);
}
@@ -156,11 +158,11 @@
#endif // HAVE_ANDROID_OS
static void
-android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase)
+android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp)
{
#ifdef HAVE_ANDROID_OS
// create the thread and assign it to the smart pointer
- sThread = new MtpThread(getMtpDatabase(env, javaDatabase));
+ sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp);
#endif
}
@@ -263,7 +265,7 @@
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"native_setup", "(Landroid/mtp/MtpDatabase;)V",
+ {"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
{"native_start", "()V", (void *)android_mtp_MtpServer_start},
{"native_stop", "()V", (void *)android_mtp_MtpServer_stop},
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 5696433..277e16c 100755
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -144,6 +144,7 @@
VIDEOEDIT_JAVA_CONSTANT_INIT("MP3", M4VIDEOEDITING_kFileType_MP3),
VIDEOEDIT_JAVA_CONSTANT_INIT("PCM", M4VIDEOEDITING_kFileType_PCM),
VIDEOEDIT_JAVA_CONSTANT_INIT("JPG", M4VIDEOEDITING_kFileType_JPG),
+ VIDEOEDIT_JAVA_CONSTANT_INIT("PNG", M4VIDEOEDITING_kFileType_PNG),
VIDEOEDIT_JAVA_CONSTANT_INIT("M4V", M4VIDEOEDITING_kFileType_M4V),
VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kFileType_Unsupported)
};
@@ -377,9 +378,7 @@
{
VIDEOEDIT_JAVA_CONSTANT_INIT("NONE", M4VSS3GPP_kVideoEffectType_None),
VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_FROM_BLACK", M4VSS3GPP_kVideoEffectType_FadeFromBlack),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_OPENING", M4VSS3GPP_kVideoEffectType_CurtainOpening),
VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_TO_BLACK", M4VSS3GPP_kVideoEffectType_FadeToBlack),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CURTAIN_CLOSING", M4VSS3GPP_kVideoEffectType_CurtainClosing),
VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL", M4VSS3GPP_kVideoEffectType_External),
VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_AND_WHITE", M4xVSS_kVideoEffectType_BlackAndWhite),
VIDEOEDIT_JAVA_CONSTANT_INIT("PINK", M4xVSS_kVideoEffectType_Pink),
@@ -1394,8 +1393,8 @@
pSettings->FileType = (M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
&converted, pEnv->GetIntField(object, fieldIds.fileType));
- if ( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG)
- {
+ if (( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG) ||
+ ( pSettings->FileType == M4VIDEOEDITING_kFileType_PNG)) {
pSettings->FileType = M4VIDEOEDITING_kFileType_ARGB8888;
}
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index 53e7de1..a8c08ac 100755
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -166,7 +166,6 @@
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE ),
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INTERNAL_STATE ),
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_LUMA_FILTER_ERROR ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_CURTAIN_FILTER_ERROR ),
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR ),
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED ),
VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE ),
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 3ea13a6..4ffb2c0 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -23,7 +23,6 @@
// XXX needed for timing latency
#include <utils/Timers.h>
-#include <sys/resource.h>
#include <media/AudioTrack.h>
#include <media/mediaplayer.h>
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
index b0e8585..a3e76d9 100644
--- a/media/libeffects/factory/EffectsFactory.c
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -257,7 +257,7 @@
}
// create effect in library
- l->desc->create_effect(uuid, sessionId, ioId, &itfe);
+ ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe);
if (ret != 0) {
LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret);
goto exit;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a41d7ab..4c4aad0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -70,7 +70,7 @@
size <<= 1;
if (audio_is_linear_pcm(format)) {
- size /= channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? 2 : 1);
+ size /= channelCount * audio_bytes_per_sample(format);
}
*frameCount = size;
@@ -258,7 +258,7 @@
int AudioRecord::frameSize() const
{
if (audio_is_linear_pcm(mFormat)) {
- return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ return channelCount()*audio_bytes_per_sample(mFormat);
} else {
return sizeof(uint8_t);
}
@@ -481,7 +481,7 @@
{
AutoMutex lock(mLock);
int active;
- status_t result;
+ status_t result = NO_ERROR;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 37fe182..31eb97a 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -298,7 +298,7 @@
int AudioTrack::frameSize() const
{
if (audio_is_linear_pcm(mFormat)) {
- return channelCount()*((format() == AUDIO_FORMAT_PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+ return channelCount()*audio_bytes_per_sample(mFormat);
} else {
return sizeof(uint8_t);
}
@@ -314,7 +314,7 @@
void AudioTrack::start()
{
sp<AudioTrackThread> t = mAudioTrackThread;
- status_t status;
+ status_t status = NO_ERROR;
LOGV("start %p", this);
if (t != 0) {
@@ -825,7 +825,7 @@
{
AutoMutex lock(mLock);
int active;
- status_t result;
+ status_t result = NO_ERROR;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 59cd1b7..a44ef5a 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -60,12 +60,13 @@
{
}
- status_t setCamera(const sp<ICamera>& camera)
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
{
- LOGV("setCamera(%p)", camera.get());
+ LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeStrongBinder(camera->asBinder());
+ data.writeStrongBinder(proxy->asBinder());
remote()->transact(SET_CAMERA, data, &reply);
return reply.readInt32();
}
@@ -434,7 +435,9 @@
LOGV("SET_CAMERA");
CHECK_INTERFACE(IMediaRecorder, data, reply);
sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
- reply->writeInt32(setCamera(camera));
+ sp<ICameraRecordingProxy> proxy =
+ interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
+ reply->writeInt32(setCamera(camera, proxy));
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
index aec96f1..8eeebbb 100644
--- a/media/libmedia/Metadata.cpp
+++ b/media/libmedia/Metadata.cpp
@@ -32,7 +32,7 @@
// All these constants below must be kept in sync with Metadata.java.
enum MetadataId {
FIRST_SYSTEM_ID = 1,
- LAST_SYSTEM_ID = 32,
+ LAST_SYSTEM_ID = 31,
FIRST_CUSTOM_ID = 8192
};
@@ -43,7 +43,6 @@
BOOLEAN_VAL,
LONG_VAL,
DOUBLE_VAL,
- TIMED_TEXT_VAL,
DATE_VAL,
BYTE_ARRAY_VAL,
};
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 9f1b3d6..7c2200e 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -21,7 +21,6 @@
#include <stdio.h>
#include <math.h>
#include <utils/Log.h>
-#include <sys/resource.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <cutils/properties.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 0100a17..9e4edd0 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -28,9 +28,9 @@
namespace android {
-status_t MediaRecorder::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
{
- LOGV("setCamera(%p)", camera.get());
+ LOGV("setCamera(%p,%p)", camera.get(), proxy.get());
if(mMediaRecorder == NULL) {
LOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
@@ -40,7 +40,7 @@
return INVALID_OPERATION;
}
- status_t ret = mMediaRecorder->setCamera(camera);
+ status_t ret = mMediaRecorder->setCamera(camera, proxy);
if (OK != ret) {
LOGV("setCamera failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 29cc019..115db1a 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -57,7 +57,8 @@
return ok;
}
-status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera)
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy)
{
LOGV("setCamera");
Mutex::Autolock lock(mLock);
@@ -65,7 +66,7 @@
LOGE("recorder is not initialized");
return NO_INIT;
}
- return mRecorder->setCamera(camera);
+ return mRecorder->setCamera(camera, proxy);
}
status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index fded98e..bbca529 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -24,11 +24,13 @@
class MediaRecorderBase;
class MediaPlayerService;
+class ICameraRecordingProxy;
class MediaRecorderClient : public BnMediaRecorder
{
public:
- virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 06fb103..d574ea3 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -21,7 +21,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/resource.h>
#include <dirent.h>
#include <unistd.h>
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 978571c..b003476 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -198,14 +198,20 @@
return OK;
}
-status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
+status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy) {
LOGV("setCamera");
if (camera == 0) {
LOGE("camera is NULL");
return BAD_VALUE;
}
+ if (proxy == 0) {
+ LOGE("camera proxy is NULL");
+ return BAD_VALUE;
+ }
mCamera = camera;
+ mCameraProxy = proxy;
return OK;
}
@@ -1235,15 +1241,17 @@
videoSize.height = mVideoHeight;
if (mCaptureTimeLapse) {
mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
- mCamera, mCameraId,
+ mCamera, mCameraProxy, mCameraId,
videoSize, mFrameRate, mPreviewSurface,
mTimeBetweenTimeLapseFrameCaptureUs);
*cameraSource = mCameraSourceTimeLapse;
} else {
*cameraSource = CameraSource::CreateFromCamera(
- mCamera, mCameraId, videoSize, mFrameRate,
+ mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
}
+ mCamera.clear();
+ mCameraProxy.clear();
if (*cameraSource == NULL) {
return UNKNOWN_ERROR;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index aa67aa7..cb9c406 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -27,6 +27,7 @@
namespace android {
class Camera;
+class ICameraRecordingProxy;
class CameraSource;
class CameraSourceTimeLapse;
class MediaSourceSplitter;
@@ -48,7 +49,7 @@
virtual status_t setVideoEncoder(video_encoder ve);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
- virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
@@ -66,6 +67,7 @@
private:
sp<ICamera> mCamera;
+ sp<ICameraRecordingProxy> mCameraProxy;
sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
sp<MediaWriter> mWriter, mWriterAux;
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
index 8413208..d133e91 100644
--- a/media/libstagefright/AACWriter.cpp
+++ b/media/libstagefright/AACWriter.cpp
@@ -27,7 +27,6 @@
#include <media/stagefright/MetaData.h>
#include <media/mediarecorder.h>
#include <sys/prctl.h>
-#include <sys/resource.h>
#include <fcntl.h>
namespace android {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d628301..167071a3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -29,6 +29,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/NativeWindowWrapper.h>
#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
#include <surfaceflinger/Surface.h>
#include <gui/SurfaceTextureClient.h>
@@ -401,11 +402,22 @@
CHECK(mem.get() != NULL);
IOMX::buffer_id buffer;
-#if 0
- err = mOMX->allocateBufferWithBackup(mNode, portIndex, mem, &buffer);
-#else
- err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
-#endif
+
+ if (!strcasecmp(
+ mComponentName.c_str(), "OMX.TI.DUCATI1.VIDEO.DECODER")) {
+ if (portIndex == kPortIndexInput && i == 0) {
+ // Only log this warning once per allocation round.
+
+ LOGW("OMX.TI.DUCATI1.VIDEO.DECODER requires the use of "
+ "OMX_AllocateBuffer instead of the preferred "
+ "OMX_UseBuffer. Vendor must fix this.");
+ }
+
+ err = mOMX->allocateBufferWithBackup(
+ mNode, portIndex, mem, &buffer);
+ } else {
+ err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
+ }
if (err != OK) {
return err;
@@ -891,6 +903,7 @@
CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
|| format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
|| format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
return mOMX->setParameter(
@@ -1639,27 +1652,33 @@
AString mime;
CHECK(msg->findString("mime", &mime));
- AString componentName;
-
- if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
- componentName = "OMX.Nvidia.h264.decode";
- } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
- componentName = "OMX.google.aac.decoder";
- } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_MPEG)) {
- componentName = "OMX.Nvidia.mp3.decoder";
- } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG2)) {
- componentName = "OMX.Nvidia.mpeg2v.decode";
- } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
- componentName = "OMX.google.mpeg4.decoder";
- } else {
- TRESPASS();
- }
+ Vector<String8> matchingCodecs;
+ OMXCodec::findMatchingCodecs(
+ mime.c_str(),
+ false, // createEncoder
+ NULL, // matchComponentName
+ 0, // flags
+ &matchingCodecs);
sp<CodecObserver> observer = new CodecObserver;
+ IOMX::node_id node = NULL;
- IOMX::node_id node;
- CHECK_EQ(omx->allocateNode(componentName.c_str(), observer, &node),
- (status_t)OK);
+ AString componentName;
+
+ for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+ ++matchIndex) {
+ componentName = matchingCodecs.itemAt(matchIndex).string();
+
+ status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+
+ if (err == OK) {
+ break;
+ }
+
+ node = NULL;
+ }
+
+ CHECK(node != NULL);
sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
observer->setNotificationMessage(notify);
@@ -2263,6 +2282,11 @@
if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
CHECK(!mFlushComplete[data2]);
mFlushComplete[data2] = true;
+
+ if (mFlushComplete[kPortIndexInput]
+ && mFlushComplete[kPortIndexOutput]) {
+ changeStateIfWeOwnAllBuffers();
+ }
} else {
CHECK_EQ(data2, OMX_ALL);
CHECK(mFlushComplete[kPortIndexInput]);
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index b10d52c..6436071 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -23,7 +23,6 @@
#include <media/stagefright/MetaData.h>
#include <media/mediarecorder.h>
#include <sys/prctl.h>
-#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 61bb2a8..ed8149a 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -115,19 +115,20 @@
size.height = -1;
sp<ICamera> camera;
- return new CameraSource(camera, 0, size, -1, NULL, false);
+ return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
}
// static
CameraSource *CameraSource::CreateFromCamera(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
const sp<Surface>& surface,
bool storeMetaDataInVideoBuffers) {
- CameraSource *source = new CameraSource(camera, cameraId,
+ CameraSource *source = new CameraSource(camera, proxy, cameraId,
videoSize, frameRate, surface,
storeMetaDataInVideoBuffers);
return source;
@@ -135,6 +136,7 @@
CameraSource::CameraSource(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
@@ -153,13 +155,15 @@
mNumGlitches(0),
mGlitchDurationThresholdUs(200000),
mCollectStats(false) {
-
mVideoSize.width = -1;
mVideoSize.height = -1;
- mInitCheck = init(camera, cameraId,
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mInitCheck = init(camera, proxy, cameraId,
videoSize, frameRate,
storeMetaDataInVideoBuffers);
+ if (mInitCheck != OK) releaseCamera();
+ IPCThreadState::self()->restoreCallingIdentity(token);
}
status_t CameraSource::initCheck() const {
@@ -167,24 +171,32 @@
}
status_t CameraSource::isCameraAvailable(
- const sp<ICamera>& camera, int32_t cameraId) {
+ const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId) {
if (camera == 0) {
mCamera = Camera::connect(cameraId);
+ if (mCamera == 0) return -EBUSY;
+ // If proxy is not passed in by applications, still use the proxy of
+ // our own Camera to simplify the code.
+ mCameraRecordingProxy = mCamera->getRecordingProxy();
mCameraFlags &= ~FLAGS_HOT_CAMERA;
} else {
+ // We get the proxy from Camera, not ICamera. We need to get the proxy
+ // to the remote Camera owned by the application. Here mCamera is a
+ // local Camera object created by us. We cannot use the proxy from
+ // mCamera here.
mCamera = Camera::create(camera);
+ if (mCamera == 0) return -EBUSY;
+ mCameraRecordingProxy = proxy;
mCameraFlags |= FLAGS_HOT_CAMERA;
}
- // Is camera available?
- if (mCamera == 0) {
- LOGE("Camera connection could not be established.");
- return -EBUSY;
- }
- if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
- mCamera->lock();
- }
+ mCamera->lock();
+ mDeathNotifier = new DeathNotifier();
+ // isBinderAlive needs linkToDeath to work.
+ mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+
return OK;
}
@@ -286,7 +298,6 @@
if (width != -1 && height != -1) {
if (!isVideoSizeSupported(width, height, sizes)) {
LOGE("Video dimension (%dx%d) is unsupported", width, height);
- releaseCamera();
return BAD_VALUE;
}
if (isSetVideoSizeSupportedByCamera) {
@@ -300,7 +311,6 @@
// If one and only one of the width and height is -1
// we reject such a request.
LOGE("Requested video size (%dx%d) is not supported", width, height);
- releaseCamera();
return BAD_VALUE;
} else { // width == -1 && height == -1
// Do not configure the camera.
@@ -318,7 +328,6 @@
if (strstr(supportedFrameRates, buf) == NULL) {
LOGE("Requested frame rate (%d) is not supported: %s",
frameRate, supportedFrameRates);
- releaseCamera();
return BAD_VALUE;
}
@@ -447,15 +456,16 @@
*/
status_t CameraSource::init(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t frameRate,
bool storeMetaDataInVideoBuffers) {
status_t err = OK;
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- if ((err = isCameraAvailable(camera, cameraId)) != OK) {
+ if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+ LOGE("Camera connection could not be established.");
return err;
}
CameraParameters params(mCamera->getParameters());
@@ -494,8 +504,6 @@
}
}
- IPCThreadState::self()->restoreCallingIdentity(token);
-
int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
if (glitchDurationUs > mGlitchDurationThresholdUs) {
mGlitchDurationThresholdUs = glitchDurationUs;
@@ -521,8 +529,14 @@
}
void CameraSource::startCameraRecording() {
- CHECK_EQ(OK, mCamera->startRecording());
- CHECK(mCamera->recordingEnabled());
+ // Reset the identity to the current thread because media server owns the
+ // camera and recording is started by the applications. The applications
+ // will connect to the camera in ICameraRecordingProxy::startRecording.
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->unlock();
+ mCamera.clear();
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
}
status_t CameraSource::start(MetaData *meta) {
@@ -544,31 +558,33 @@
mStartTimeUs = startTimeUs;
}
- // Call setListener first before calling startCameraRecording()
- // to avoid recording frames being dropped.
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- mCamera->setListener(new CameraSourceListener(this));
startCameraRecording();
- IPCThreadState::self()->restoreCallingIdentity(token);
mStarted = true;
return OK;
}
void CameraSource::stopCameraRecording() {
- mCamera->setListener(NULL);
- mCamera->stopRecording();
+ mCameraRecordingProxy->stopRecording();
}
void CameraSource::releaseCamera() {
LOGV("releaseCamera");
- if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
- LOGV("Camera was cold when we started, stopping preview");
- mCamera->stopPreview();
+ if (mCamera != 0) {
+ if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
+ LOGV("Camera was cold when we started, stopping preview");
+ mCamera->stopPreview();
+ mCamera->disconnect();
+ } else {
+ // Unlock the camera so the application can lock it back.
+ mCamera->unlock();
+ }
+ mCamera.clear();
}
- mCamera->unlock();
- mCamera.clear();
- mCamera = 0;
+ if (mCameraRecordingProxy != 0) {
+ mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+ mCameraRecordingProxy.clear();
+ }
mCameraFlags = 0;
}
@@ -578,7 +594,6 @@
mStarted = false;
mFrameAvailableCondition.signal();
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
releaseQueuedFrames();
while (!mFramesBeingEncoded.empty()) {
if (NO_ERROR !=
@@ -589,7 +604,6 @@
}
stopCameraRecording();
releaseCamera();
- IPCThreadState::self()->restoreCallingIdentity(token);
if (mCollectStats) {
LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
@@ -607,8 +621,8 @@
}
void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (mCamera != NULL) {
- mCamera->releaseRecordingFrame(frame);
+ if (mCameraRecordingProxy != NULL) {
+ mCameraRecordingProxy->releaseRecordingFrame(frame);
}
}
@@ -627,9 +641,7 @@
}
void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
releaseRecordingFrame(frame);
- IPCThreadState::self()->restoreCallingIdentity(token);
}
void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -669,7 +681,11 @@
Mutex::Autolock autoLock(mLock);
while (mStarted && mFramesReceived.empty()) {
if (NO_ERROR !=
- mFrameAvailableCondition.waitRelative(mLock, 3000000000LL)) {
+ mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
+ if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+ LOGW("camera recording proxy is gone");
+ return ERROR_END_OF_STREAM;
+ }
LOGW("Timed out waiting for incoming camera video frames: %lld us",
mLastFrameTimestampUs);
}
@@ -745,4 +761,17 @@
return mIsMetaDataStoredInVideoBuffers;
}
+CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
+ mSource = source;
+}
+
+void CameraSource::ProxyListener::dataCallbackTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+ mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
+}
+
+void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ LOGI("Camera recording proxy died");
+}
+
} // namespace android
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index cc22574..fe78c46 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -39,6 +39,7 @@
// static
CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
@@ -46,7 +47,7 @@
int64_t timeBetweenTimeLapseFrameCaptureUs) {
CameraSourceTimeLapse *source = new
- CameraSourceTimeLapse(camera, cameraId,
+ CameraSourceTimeLapse(camera, proxy, cameraId,
videoSize, videoFrameRate, surface,
timeBetweenTimeLapseFrameCaptureUs);
@@ -61,12 +62,13 @@
CameraSourceTimeLapse::CameraSourceTimeLapse(
const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
Size videoSize,
int32_t videoFrameRate,
const sp<Surface>& surface,
int64_t timeBetweenTimeLapseFrameCaptureUs)
- : CameraSource(camera, cameraId, videoSize, videoFrameRate, surface, true),
+ : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
mTimeBetweenTimeLapseFrameCaptureUs(timeBetweenTimeLapseFrameCaptureUs),
mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
mLastTimeLapseFrameRealTimestampUs(0),
@@ -315,7 +317,7 @@
pthread_attr_destroy(&attr);
} else {
LOGV("start time lapse recording using video camera");
- CHECK_EQ(OK, mCamera->startRecording());
+ CameraSource::startCameraRecording();
}
}
@@ -337,8 +339,7 @@
// play the recording sound.
mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
} else {
- mCamera->setListener(NULL);
- mCamera->stopRecording();
+ CameraSource::stopCameraRecording();
}
if (mLastReadBufferCopy) {
mLastReadBufferCopy->release();
@@ -347,9 +348,8 @@
}
void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (!mUseStillCameraForTimeLapse &&
- mCamera != NULL) {
- mCamera->releaseRecordingFrame(frame);
+ if (!mUseStillCameraForTimeLapse) {
+ CameraSource::releaseRecordingFrame(frame);
}
}
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 4e4f289..02eeb40 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -466,6 +466,8 @@
MPEG2TSWriter::MPEG2TSWriter(int fd)
: mFile(fdopen(dup(fd), "wb")),
+ mWriteCookie(NULL),
+ mWriteFunc(NULL),
mStarted(false),
mNumSourcesDone(0),
mNumTSPacketsWritten(0),
@@ -475,6 +477,21 @@
MPEG2TSWriter::MPEG2TSWriter(const char *filename)
: mFile(fopen(filename, "wb")),
+ mWriteCookie(NULL),
+ mWriteFunc(NULL),
+ mStarted(false),
+ mNumSourcesDone(0),
+ mNumTSPacketsWritten(0),
+ mNumTSPacketsBeforeMeta(0) {
+ init();
+}
+
+MPEG2TSWriter::MPEG2TSWriter(
+ void *cookie,
+ ssize_t (*write)(void *cookie, const void *data, size_t size))
+ : mFile(NULL),
+ mWriteCookie(cookie),
+ mWriteFunc(write),
mStarted(false),
mNumSourcesDone(0),
mNumTSPacketsWritten(0),
@@ -483,7 +500,7 @@
}
void MPEG2TSWriter::init() {
- CHECK(mFile != NULL);
+ CHECK(mFile != NULL || mWriteFunc != NULL);
mLooper = new ALooper;
mLooper->setName("MPEG2TSWriter");
@@ -502,8 +519,10 @@
mLooper->unregisterHandler(mReflector->id());
mLooper->stop();
- fclose(mFile);
- mFile = NULL;
+ if (mFile != NULL) {
+ fclose(mFile);
+ mFile = NULL;
+ }
}
status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
@@ -718,7 +737,7 @@
static const unsigned kContinuityCounter = 5;
buffer->data()[3] |= kContinuityCounter;
- CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
}
void MPEG2TSWriter::writeProgramMap() {
@@ -794,7 +813,7 @@
*ptr++ = 0x00;
*ptr++ = 0x00;
- CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
}
void MPEG2TSWriter::writeAccessUnit(
@@ -890,7 +909,7 @@
memcpy(ptr, accessUnit->data(), copy);
- CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
size_t offset = copy;
while (offset < accessUnit->size()) {
@@ -923,7 +942,7 @@
}
memcpy(ptr, accessUnit->data() + offset, copy);
- CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile),
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
buffer->size());
offset += copy;
@@ -939,5 +958,13 @@
}
}
+ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
+ if (mFile != NULL) {
+ return fwrite(data, 1, size, mFile);
+ }
+
+ return (*mWriteFunc)(mWriteCookie, data, size);
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5fe511f..5582f92 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -889,11 +889,17 @@
uint32_t entry_count = U32_AT(&buffer[4]);
if (entry_count > 1) {
- // For now we only support a single type of media per track.
-
- mLastTrack->skipTrack = true;
- *offset += chunk_size;
- break;
+ // For 3GPP timed text, there could be multiple tx3g boxes contain
+ // multiple text display formats. These formats will be used to
+ // display the timed text.
+ const char *mime;
+ CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ // For now we only support a single type of media per track.
+ mLastTrack->skipTrack = true;
+ *offset += chunk_size;
+ break;
+ }
}
off64_t stop_offset = *offset + chunk_size;
@@ -1324,9 +1330,53 @@
return parseDrmSINF(offset, data_offset);
}
+ case FOURCC('h', 'd', 'l', 'r'):
+ {
+ uint32_t buffer;
+ if (mDataSource->readAt(
+ data_offset + 8, &buffer, 4) < 4) {
+ return ERROR_IO;
+ }
+
+ uint32_t type = ntohl(buffer);
+ // For the 3GPP file format, the handler-type within the 'hdlr' box
+ // shall be 'text'
+ if (type == FOURCC('t', 'e', 'x', 't')) {
+ mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
case FOURCC('t', 'x', '3', 'g'):
{
- mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+ uint32_t type;
+ const void *data;
+ size_t size = 0;
+ if (!mLastTrack->meta->findData(
+ kKeyTextFormatData, &type, &data, &size)) {
+ size = 0;
+ }
+
+ uint8_t *buffer = new uint8_t[size + chunk_size];
+
+ if (size > 0) {
+ memcpy(buffer, data, size);
+ }
+
+ if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
+ < chunk_size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ mLastTrack->meta->setData(
+ kKeyTextFormatData, 0, buffer, size + chunk_size);
+
+ delete[] buffer;
*offset += chunk_size;
break;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 28add18..f075699d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -22,7 +22,6 @@
#include <pthread.h>
#include <sys/prctl.h>
-#include <sys/resource.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaBuffer.h>
@@ -48,10 +47,6 @@
static const uint8_t kNalUnitTypePicParamSet = 0x08;
static const int64_t kInitialDelayTimeUs = 700000LL;
-// Using longer adjustment period to suppress fluctuations in
-// the audio encoding paths
-static const int64_t kVideoMediaTimeAdjustPeriodTimeUs = 600000000LL; // 10 minutes
-
class MPEG4Writer::Track {
public:
Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
@@ -89,8 +84,6 @@
int64_t mTrackDurationUs;
int64_t mMaxChunkDurationUs;
- // For realtime applications, we need to adjust the media clock
- // for video track based on the audio media clock
bool mIsRealTimeRecording;
int64_t mMaxTimeStampUs;
int64_t mEstimatedTrackSizeBytes;
@@ -176,28 +169,9 @@
int64_t mPreviousTrackTimeUs;
int64_t mTrackEveryTimeDurationUs;
- // Has the media time adjustment for video started?
- bool mIsMediaTimeAdjustmentOn;
- // The time stamp when previous media time adjustment period starts
- int64_t mPrevMediaTimeAdjustTimestampUs;
- // Number of vidoe frames whose time stamp may be adjusted
- int64_t mMediaTimeAdjustNumFrames;
- // The sample number when previous meida time adjustmnet period starts
- int64_t mPrevMediaTimeAdjustSample;
- // The total accumulated drift time within a period of
- // kVideoMediaTimeAdjustPeriodTimeUs.
- int64_t mTotalDriftTimeToAdjustUs;
- // The total accumalated drift time since the start of the recording
- // excluding the current time adjustment period
- int64_t mPrevTotalAccumDriftTimeUs;
-
// Update the audio track's drift information.
void updateDriftTime(const sp<MetaData>& meta);
- // Adjust the time stamp of the video track according to
- // the drift time information from the audio track.
- void adjustMediaTime(int64_t *timestampUs);
-
static void *ThreadWrapper(void *me);
status_t threadEntry();
@@ -231,6 +205,8 @@
// Duration is time scale based
void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+
+ bool isTrackMalFormed() const;
void sendTrackSummary(bool hasMultipleTracks);
// Write the boxes
@@ -1513,12 +1489,7 @@
mNumSttsTableEntries = 0;
mNumCttsTableEntries = 0;
mMdatSizeBytes = 0;
- mIsMediaTimeAdjustmentOn = false;
- mPrevMediaTimeAdjustTimestampUs = 0;
- mMediaTimeAdjustNumFrames = 0;
- mPrevMediaTimeAdjustSample = 0;
- mTotalDriftTimeToAdjustUs = 0;
- mPrevTotalAccumDriftTimeUs = 0;
+
mMaxChunkDurationUs = 0;
mHasNegativeCttsDeltaDuration = false;
@@ -1817,128 +1788,6 @@
}
/*
-* The video track's media time adjustment for real-time applications
-* is described as follows:
-*
-* First, the media time adjustment is done for every period of
-* kVideoMediaTimeAdjustPeriodTimeUs. kVideoMediaTimeAdjustPeriodTimeUs
-* is currently a fixed value chosen heuristically. The value of
-* kVideoMediaTimeAdjustPeriodTimeUs should not be very large or very small
-* for two considerations: on one hand, a relatively large value
-* helps reduce large fluctuation of drift time in the audio encoding
-* path; while on the other hand, a relatively small value helps keep
-* restoring synchronization in audio/video more frequently. Note for the
-* very first period of kVideoMediaTimeAdjustPeriodTimeUs, there is
-* no media time adjustment for the video track.
-*
-* Second, the total accumulated audio track time drift found
-* in a period of kVideoMediaTimeAdjustPeriodTimeUs is distributed
-* over a stream of incoming video frames. The number of video frames
-* affected is determined based on the number of recorded video frames
-* within the past kVideoMediaTimeAdjustPeriodTimeUs period.
-* We choose to distribute the drift time over only a portion
-* (rather than all) of the total number of recorded video frames
-* in order to make sure that the video track media time adjustment is
-* completed for the current period before the next video track media
-* time adjustment period starts. Currently, the portion chosen is a
-* half (0.5).
-*
-* Last, various additional checks are performed to ensure that
-* the actual audio encoding path does not have too much drift.
-* In particular, 1) we want to limit the average incremental time
-* adjustment for each video frame to be less than a threshold
-* for a single period of kVideoMediaTimeAdjustPeriodTimeUs.
-* Currently, the threshold is set to 5 ms. If the average incremental
-* media time adjustment for a video frame is larger than the
-* threshold, the audio encoding path has too much time drift.
-* 2) We also want to limit the total time drift in the audio
-* encoding path to be less than a threshold for a period of
-* kVideoMediaTimeAdjustPeriodTimeUs. Currently, the threshold
-* is 0.5% of kVideoMediaTimeAdjustPeriodTimeUs. If the time drift of
-* the audio encoding path is larger than the threshold, the audio
-* encoding path has too much time drift. We treat the large time
-* drift of the audio encoding path as errors, since there is no
-* way to keep audio/video in synchronization for real-time
-* applications if the time drift is too large unless we drop some
-* video frames, which has its own problems that we don't want
-* to get into for the time being.
-*/
-void MPEG4Writer::Track::adjustMediaTime(int64_t *timestampUs) {
- if (*timestampUs - mPrevMediaTimeAdjustTimestampUs >=
- kVideoMediaTimeAdjustPeriodTimeUs) {
-
- LOGV("New media time adjustment period at %lld us", *timestampUs);
- mIsMediaTimeAdjustmentOn = true;
- mMediaTimeAdjustNumFrames =
- (mNumSamples - mPrevMediaTimeAdjustSample) >> 1;
-
- mPrevMediaTimeAdjustTimestampUs = *timestampUs;
- mPrevMediaTimeAdjustSample = mNumSamples;
- int64_t totalAccumDriftTimeUs = mOwner->getDriftTimeUs();
- mTotalDriftTimeToAdjustUs =
- totalAccumDriftTimeUs - mPrevTotalAccumDriftTimeUs;
-
- mPrevTotalAccumDriftTimeUs = totalAccumDriftTimeUs;
-
- // Check on incremental adjusted time per frame
- int64_t adjustTimePerFrameUs =
- mTotalDriftTimeToAdjustUs / mMediaTimeAdjustNumFrames;
-
- if (adjustTimePerFrameUs < 0) {
- adjustTimePerFrameUs = -adjustTimePerFrameUs;
- }
- if (adjustTimePerFrameUs >= 5000) {
- LOGE("Adjusted time per video frame is %lld us",
- adjustTimePerFrameUs);
- CHECK(!"Video frame time adjustment is too large!");
- }
-
- // Check on total accumulated time drift within a period of
- // kVideoMediaTimeAdjustPeriodTimeUs.
- int64_t driftPercentage = (mTotalDriftTimeToAdjustUs * 1000)
- / kVideoMediaTimeAdjustPeriodTimeUs;
-
- if (driftPercentage < 0) {
- driftPercentage = -driftPercentage;
- }
- if (driftPercentage > 5) {
- LOGE("Audio track has time drift %lld us over %lld us",
- mTotalDriftTimeToAdjustUs,
- kVideoMediaTimeAdjustPeriodTimeUs);
-
- CHECK(!"The audio track media time drifts too much!");
- }
-
- }
-
- if (mIsMediaTimeAdjustmentOn) {
- if (mNumSamples - mPrevMediaTimeAdjustSample <=
- mMediaTimeAdjustNumFrames) {
-
- // Do media time incremental adjustment
- int64_t incrementalAdjustTimeUs =
- (mTotalDriftTimeToAdjustUs *
- (mNumSamples - mPrevMediaTimeAdjustSample))
- / mMediaTimeAdjustNumFrames;
-
- *timestampUs +=
- (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs);
-
- LOGV("Incremental video frame media time adjustment: %lld us",
- (incrementalAdjustTimeUs + mPrevTotalAccumDriftTimeUs));
- } else {
- // Within the remaining adjustment period,
- // no incremental adjustment is needed.
- *timestampUs +=
- (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs);
-
- LOGV("Fixed video frame media time adjustment: %lld us",
- (mTotalDriftTimeToAdjustUs + mPrevTotalAccumDriftTimeUs));
- }
- }
-}
-
-/*
* Updates the drift time from the audio track so that
* the video track can get the updated drift time information
* from the file writer. The fluctuation of the drift time of the audio
@@ -1975,7 +1824,17 @@
int64_t previousPausedDurationUs = 0;
int64_t timestampUs = 0;
int64_t cttsDeltaTimeUs = 0;
+ bool hasBFrames = false;
+#if 1
+ // XXX: Samsung's video encoder's output buffer timestamp
+ // is not correct. see bug 4724339
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("rw.media.record.hasb", value, NULL) &&
+ (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
+ hasBFrames = true;
+ }
+#endif
if (mIsAudio) {
prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
} else {
@@ -2071,32 +1930,6 @@
int32_t isSync = false;
meta_data->findInt32(kKeyIsSyncFrame, &isSync);
-
- /*
- * The original timestamp found in the data buffer will be modified as below:
- *
- * There is a playback offset into this track if the track's start time
- * is not the same as the movie start time, which will be recorded in edst
- * box of the output file. The playback offset is to make sure that the
- * starting time of the audio/video tracks are synchronized. Although the
- * track's media timestamp may be subject to various modifications
- * as outlined below, the track's playback offset time remains unchanged
- * once the first data buffer of the track is received.
- *
- * The media time stamp will be calculated by subtracting the playback offset
- * (and potential pause durations) from the original timestamp in the buffer.
- *
- * If this track is a video track for a real-time recording application with
- * both audio and video tracks, its media timestamp will subject to further
- * modification based on the media clock of the audio track. This modification
- * is needed for the purpose of maintaining good audio/video synchronization.
- *
- * If the recording session is paused and resumed multiple times, the track
- * media timestamp will be modified as if the recording session had never been
- * paused at all during playback of the recorded output file. In other words,
- * the output file will have no memory of pause/resume durations.
- *
- */
CHECK(meta_data->findInt64(kKeyTime, ×tampUs));
////////////////////////////////////////////////////////////////////////////////
@@ -2118,7 +1951,7 @@
timestampUs -= previousPausedDurationUs;
CHECK(timestampUs >= 0);
- if (!mIsAudio) {
+ if (!mIsAudio && hasBFrames) {
/*
* Composition time: timestampUs
* Decoding time: decodingTimeUs
@@ -2137,32 +1970,13 @@
timestampUs, cttsDeltaTimeUs);
}
- // Media time adjustment for real-time applications
if (mIsRealTimeRecording) {
if (mIsAudio) {
updateDriftTime(meta_data);
- } else {
- adjustMediaTime(×tampUs);
}
}
CHECK(timestampUs >= 0);
- if (mNumSamples > 1) {
- if (timestampUs <= lastTimestampUs) {
- LOGW("Frame arrives too late!");
- // Don't drop the late frame, since dropping a frame may cause
- // problems later during playback
-
- // The idea here is to avoid having two or more samples with the
- // same timestamp in the output file.
- if (mTimeScale >= 1000000LL) {
- timestampUs = lastTimestampUs + 1;
- } else {
- timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
- }
- }
- }
-
LOGV("%s media time stamp: %lld and previous paused duration %lld",
mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
if (timestampUs > mTrackDurationUs) {
@@ -2269,11 +2083,10 @@
}
- if (mSampleSizes.empty() || // no samples written
- (!mIsAudio && mNumStssTableEntries == 0) || // no sync frames for video
- (OK != checkCodecSpecificData())) { // no codec specific data
+ if (isTrackMalFormed()) {
err = ERROR_MALFORMED;
}
+
mOwner->trackProgressStatus(mTrackId, -1, err);
// Last chunk
@@ -2323,6 +2136,24 @@
return err;
}
+bool MPEG4Writer::Track::isTrackMalFormed() const {
+ if (mSampleSizes.empty()) { // no samples written
+ LOGE("The number of recorded samples is 0");
+ return true;
+ }
+
+ if (!mIsAudio && mNumStssTableEntries == 0) { // no sync frames for video
+ LOGE("There are no sync frames for video track");
+ return true;
+ }
+
+ if (OK != checkCodecSpecificData()) { // no codec specific data
+ return true;
+ }
+
+ return false;
+}
+
void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
// Send track summary only if test mode is enabled.
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c4fcc79..e36b01f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -180,6 +180,7 @@
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "G711Decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW, "OMX.google.g711.mlaw.decoder" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW, "G711Decoder" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.decode" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
@@ -187,12 +188,14 @@
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.google.mpeg4.decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.decode" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.google.h263.decoder" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.DECODER" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.Nvidia.h264.decode" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
@@ -387,7 +390,10 @@
quirks |= kDefersOutputBufferAllocation;
}
- if (!strncmp(componentName, "OMX.TI.", 7)) {
+ if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) {
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ } else if (!strncmp(componentName, "OMX.TI.", 7)) {
// Apparently I must not use OMX_UseBuffer on either input or
// output ports on any of the TI components or quote:
// "(I) may have unexpected problem (sic) which can be timing related
@@ -1390,6 +1396,7 @@
CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
|| format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
|| format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
|| format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
err = mOMX->setParameter(
@@ -1831,7 +1838,7 @@
}
}
- LOGV("native_window_set_usage usage=0x%x", usage);
+ LOGV("native_window_set_usage usage=0x%lx", usage);
err = native_window_set_usage(
mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
if (err != 0) {
@@ -1983,7 +1990,14 @@
int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
CHECK(mIsEncoder);
- CHECK(!mDecodingTimeList.empty());
+
+ if (mDecodingTimeList.empty()) {
+ CHECK(mNoMoreOutputData);
+ // No corresponding input frame available.
+ // This could happen when EOS is reached.
+ return 0;
+ }
+
List<int64_t>::iterator it = mDecodingTimeList.begin();
int64_t timeUs = *it;
@@ -2152,11 +2166,6 @@
buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
}
- if (mIsEncoder) {
- int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
- buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
- }
-
buffer->meta_data()->setPointer(
kKeyPlatformPrivate,
msg.u.extended_buffer_data.platform_private);
@@ -2170,6 +2179,11 @@
mNoMoreOutputData = true;
}
+ if (mIsEncoder) {
+ int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
+ buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+ }
+
if (mTargetTimeUs >= 0) {
CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
@@ -3782,7 +3796,9 @@
size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
- if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+ if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+ return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
+ } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
} else if (type < 0 || (size_t)type >= numNames) {
return "UNKNOWN";
@@ -4200,6 +4216,10 @@
mNode, OMX_IndexConfigCommonOutputCrop,
&rect, sizeof(rect));
+ CODEC_LOGI(
+ "video dimensions are %ld x %ld",
+ video_def->nFrameWidth, video_def->nFrameHeight);
+
if (err == OK) {
CHECK_GE(rect.nLeft, 0);
CHECK_GE(rect.nTop, 0);
@@ -4214,6 +4234,10 @@
rect.nTop,
rect.nLeft + rect.nWidth - 1,
rect.nTop + rect.nHeight - 1);
+
+ CODEC_LOGI(
+ "Crop rect is %ld x %ld @ (%ld, %ld)",
+ rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
} else {
mOutputFormat->setRect(
kKeyCropRect,
@@ -4222,7 +4246,6 @@
video_def->nFrameHeight - 1);
}
}
-
break;
}
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 1560b8e..29e6907 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -730,8 +730,9 @@
off64_t size;
if (mSource->getSize(&size) == OK) {
uint64_t bps = approxBitrate();
-
- mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
+ if (bps != 0) {
+ mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
+ }
}
break;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index eb135ab..a8a094e 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -416,12 +416,16 @@
uint32_t delta = mTimeToSample[2 * i + 1];
for (uint32_t j = 0; j < n; ++j) {
- CHECK(sampleIndex < mNumSampleSizes);
+ if (sampleIndex < mNumSampleSizes) {
+ // Technically this should always be the case if the file
+ // is well-formed, but you know... there's (gasp) malformed
+ // content out there.
- mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
+ mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
- mSampleTimeEntries[sampleIndex].mCompositionTime =
- sampleTime + getCompositionTimeOffset(sampleIndex);
+ mSampleTimeEntries[sampleIndex].mCompositionTime =
+ sampleTime + getCompositionTimeOffset(sampleIndex);
+ }
++sampleIndex;
sampleTime += delta;
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index a08eb7b..100d8a3 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -30,7 +30,6 @@
#include <sys/prctl.h>
#include <sys/time.h>
-#include <sys/resource.h>
#include <media/stagefright/MediaDebug.h>
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index 26eda0c..7072d58 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -33,26 +33,25 @@
#include <utils/Errors.h>
-/* The extractor lifetime is short - just long enough to get
- * the media sources constructed - so the shared lib needs to remain open
- * beyond the lifetime of the extractor. So keep the handle as a global
- * rather than a member of the extractor
- */
-void *gVendorLibHandle = NULL;
-
namespace android {
-static Mutex gWVMutex;
+Mutex WVMExtractor::sMutex;
+uint32_t WVMExtractor::sActiveExtractors = 0;
+void *WVMExtractor::sVendorLibHandle = NULL;
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
: mDataSource(source) {
{
- Mutex::Autolock autoLock(gWVMutex);
- if (gVendorLibHandle == NULL) {
- gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+ Mutex::Autolock autoLock(sMutex);
+
+ if (sVendorLibHandle == NULL) {
+ CHECK(sActiveExtractors == 0);
+ sVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
}
- if (gVendorLibHandle == NULL) {
+ sActiveExtractors++;
+
+ if (sVendorLibHandle == NULL) {
LOGE("Failed to open libwvm.so");
return;
}
@@ -60,7 +59,7 @@
typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
GetInstanceFunc getInstanceFunc =
- (GetInstanceFunc) dlsym(gVendorLibHandle,
+ (GetInstanceFunc) dlsym(sVendorLibHandle,
"_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
if (getInstanceFunc) {
@@ -72,6 +71,17 @@
}
WVMExtractor::~WVMExtractor() {
+ Mutex::Autolock autoLock(sMutex);
+
+ CHECK(sActiveExtractors > 0);
+ sActiveExtractors--;
+
+ // Close lib after last use
+ if (sActiveExtractors == 0) {
+ if (sVendorLibHandle != NULL)
+ dlclose(sVendorLibHandle);
+ sVendorLibHandle = NULL;
+ }
}
size_t WVMExtractor::countTracks() {
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index ed6846c..967f126 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -41,6 +41,7 @@
static Mutex gNetworkThreadLock;
static base::Thread *gNetworkThread = NULL;
static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
static void InitializeNetworkThreadIfNecessary() {
Mutex::Autolock autoLock(gNetworkThreadLock);
@@ -52,6 +53,8 @@
gReqContext = new SfRequestContext;
+ gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
+
net::AndroidNetworkLibrary::RegisterSharedInstance(
new SfNetworkLibrary);
}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC.cpp b/media/libstagefright/codecs/aacdec/SoftAAC.cpp
index 7ce6128..bbd6dbb 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC.cpp
@@ -367,7 +367,15 @@
inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
inHeader->nOffset += mConfig->inputBufferUsedLength;
} else {
+ LOGW("AAC decoder returned error %d, substituting silence",
+ decoderErr);
+
memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
+
+ // Discard input buffer.
+ inHeader->nFilledLen = 0;
+
+ // fall through
}
if (mUpsamplingFactor == 2) {
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
index e9ce719..7e83163 100644
--- a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -117,11 +117,27 @@
addPort(def);
}
+static int GetCPUCoreCount() {
+ int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+ CHECK(cpuCoreCount >= 1);
+ LOGV("Number of CPU cores: %d", cpuCoreCount);
+ return cpuCoreCount;
+}
+
status_t SoftVPX::initDecoder() {
mCtx = new vpx_codec_ctx_t;
vpx_codec_err_t vpx_err;
+ vpx_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+ cfg.threads = GetCPUCoreCount();
if ((vpx_err = vpx_codec_dec_init(
- (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0))) {
+ (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, &cfg, 0))) {
LOGE("on2 decoder failed to initialize. (%d)", vpx_err);
return UNKNOWN_ERROR;
}
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 830d2e0..ec7bd1c 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -139,7 +139,8 @@
}
status_t SoftAVC::initDecoder() {
- if (H264SwDecInit(&mHandle, 1) == H264SWDEC_OK) {
+ // Force decoder to output buffers in display order.
+ if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
return OK;
}
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 3439efd..1cc85e8 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -52,7 +52,7 @@
kInputPortIndex = 0,
kOutputPortIndex = 1,
kNumInputBuffers = 8,
- kNumOutputBuffers = 16,
+ kNumOutputBuffers = 2,
};
enum EOSStatus {
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index b28d947..5cc3f78 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ColorConverter"
+#include <utils/Log.h>
+
#include <media/stagefright/ColorConverter.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaErrors.h>
@@ -42,6 +46,7 @@
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
return true;
default:
@@ -113,6 +118,10 @@
err = convertYUV420SemiPlanar(src, dst);
break;
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ err = convertTIYUV420PackedSemiPlanar(src, dst);
+ break;
+
default:
{
CHECK(!"Should not be here. Unknown color conversion.");
@@ -417,6 +426,73 @@
return OK;
}
+status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint8_t *kAdjustedClip = initClip();
+
+ if (!((dst.mWidth & 3) == 0
+ && (src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
+ const uint8_t *src_y = (const uint8_t *)src.mBits;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed u = (signed)src_u[x & ~1] - 128;
+ signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = (tmp1 + u_b) / 256;
+ signed g1 = (tmp1 + v_g + u_g) / 256;
+ signed r1 = (tmp1 + v_r) / 256;
+
+ signed tmp2 = y2 * 298;
+ signed b2 = (tmp2 + u_b) / 256;
+ signed g2 = (tmp2 + v_g + u_g) / 256;
+ signed r2 = (tmp2 + v_r) / 256;
+
+ uint32_t rgb1 =
+ ((kAdjustedClip[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
+
+ dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+ }
+
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth;
+ }
+
+ dst_ptr += dst.mWidth / 2;
+ }
+
+ return OK;
+}
+
uint8_t *ColorConverter::initClip() {
static const signed kClipMin = -278;
static const signed kClipMax = 535;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4e8ee4..a4ca32d 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -50,6 +50,9 @@
mCropBottom = mHeight - 1;
}
+ mCropWidth = mCropRight - mCropLeft + 1;
+ mCropHeight = mCropBottom - mCropTop + 1;
+
int32_t rotationDegrees;
if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
rotationDegrees = 0;
@@ -60,17 +63,18 @@
switch (mColorFormat) {
case OMX_COLOR_FormatYUV420Planar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
{
halFormat = HAL_PIXEL_FORMAT_YV12;
- bufWidth = (mWidth + 1) & ~1;
- bufHeight = (mHeight + 1) & ~1;
+ bufWidth = (mCropWidth + 1) & ~1;
+ bufHeight = (mCropHeight + 1) & ~1;
break;
}
default:
halFormat = HAL_PIXEL_FORMAT_RGB_565;
- bufWidth = mWidth;
- bufHeight = mHeight;
+ bufWidth = mCropWidth;
+ bufHeight = mCropHeight;
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_Format16bitRGB565);
@@ -79,8 +83,8 @@
}
CHECK(mNativeWindow != NULL);
- CHECK(mWidth > 0);
- CHECK(mHeight > 0);
+ CHECK(mCropWidth > 0);
+ CHECK(mCropHeight > 0);
CHECK(mConverter == NULL || mConverter->isValid());
CHECK_EQ(0,
@@ -109,14 +113,6 @@
CHECK_EQ(0, native_window_set_buffers_transform(
mNativeWindow.get(), transform));
}
-
- android_native_rect_t crop;
- crop.left = mCropLeft;
- crop.top = mCropTop;
- crop.right = mCropRight + 1;
- crop.bottom = mCropBottom + 1;
-
- CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
}
SoftwareRenderer::~SoftwareRenderer() {
@@ -142,7 +138,7 @@
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- Rect bounds(mWidth, mHeight);
+ Rect bounds(mCropWidth, mCropHeight);
void *dst;
CHECK_EQ(0, mapper.lock(
@@ -152,13 +148,11 @@
mConverter->convert(
data,
mWidth, mHeight,
- 0, 0, mWidth - 1, mHeight - 1,
+ mCropLeft, mCropTop, mCropRight, mCropBottom,
dst,
buf->stride, buf->height,
- 0, 0, mWidth - 1, mHeight - 1);
- } else {
- CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
-
+ 0, 0, mCropWidth - 1, mCropHeight - 1);
+ } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
const uint8_t *src_y = (const uint8_t *)data;
const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
@@ -170,22 +164,57 @@
uint8_t *dst_v = dst_y + dst_y_size;
uint8_t *dst_u = dst_v + dst_c_size;
- for (int y = 0; y < mHeight; ++y) {
- memcpy(dst_y, src_y, mWidth);
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
src_y += mWidth;
dst_y += buf->stride;
}
- for (int y = 0; y < (mHeight + 1) / 2; ++y) {
- memcpy(dst_u, src_u, (mWidth + 1) / 2);
- memcpy(dst_v, src_v, (mWidth + 1) / 2);
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
+ memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
src_u += mWidth / 2;
src_v += mWidth / 2;
dst_u += dst_c_stride;
dst_v += dst_c_stride;
}
+ } else {
+ CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
+
+ const uint8_t *src_y =
+ (const uint8_t *)data;
+
+ const uint8_t *src_uv =
+ (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
+
+ uint8_t *dst_y = (uint8_t *)dst;
+
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ size_t tmp = (mCropWidth + 1) / 2;
+ for (size_t x = 0; x < tmp; ++x) {
+ dst_u[x] = src_uv[2 * x];
+ dst_v[x] = src_uv[2 * x + 1];
+ }
+
+ src_uv += mWidth;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
}
CHECK_EQ(0, mapper.unlock(buf->handle));
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 012d9ad..f1a2a60 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -296,6 +296,8 @@
new M3UParser(url, buffer->data(), buffer->size());
if (playlist->initCheck() != OK) {
+ LOGE("failed to parse .m3u8 playlist");
+
return NULL;
}
@@ -406,13 +408,20 @@
if (firstTime) {
Mutex::Autolock autoLock(mLock);
- int32_t targetDuration;
- if (!mPlaylist->isComplete()
- || !mPlaylist->meta()->findInt32(
- "target-duration", &targetDuration)) {
+ if (!mPlaylist->isComplete()) {
mDurationUs = -1;
} else {
- mDurationUs = 1000000ll * targetDuration * mPlaylist->size();
+ mDurationUs = 0;
+ for (size_t i = 0; i < mPlaylist->size(); ++i) {
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(
+ i, NULL /* uri */, &itemMeta));
+
+ int64_t itemDurationUs;
+ CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+ mDurationUs += itemDurationUs;
+ }
}
}
@@ -429,14 +438,26 @@
bool bandwidthChanged = false;
if (mSeekTimeUs >= 0) {
- int32_t targetDuration;
- if (mPlaylist->isComplete() &&
- mPlaylist->meta()->findInt32(
- "target-duration", &targetDuration)) {
- int64_t seekTimeSecs = (mSeekTimeUs + 500000ll) / 1000000ll;
- int64_t index = seekTimeSecs / targetDuration;
+ if (mPlaylist->isComplete()) {
+ size_t index = 0;
+ int64_t segmentStartUs = 0;
+ while (index < mPlaylist->size()) {
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(
+ index, NULL /* uri */, &itemMeta));
- if (index >= 0 && index < mPlaylist->size()) {
+ int64_t itemDurationUs;
+ CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+ if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
+ break;
+ }
+
+ segmentStartUs += itemDurationUs;
+ ++index;
+ }
+
+ if (index < mPlaylist->size()) {
int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
if (newSeqNumber != mSeqNumber) {
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 2eb180a..123fbf8 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -64,14 +64,21 @@
}
bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
- uri->clear();
- if (meta) { *meta = NULL; }
+ if (uri) {
+ uri->clear();
+ }
+
+ if (meta) {
+ *meta = NULL;
+ }
if (index >= mItems.size()) {
return false;
}
- *uri = mItems.itemAt(index).mURI;
+ if (uri) {
+ *uri = mItems.itemAt(index).mURI;
+ }
if (meta) {
*meta = mItems.itemAt(index).mMeta;
@@ -179,7 +186,7 @@
if (mIsVariantPlaylist) {
return ERROR_MALFORMED;
}
- err = parseMetaData(line, &itemMeta, "duration");
+ err = parseMetaDataDuration(line, &itemMeta, "durationUs");
} else if (line.startsWith("#EXT-X-DISCONTINUITY")) {
if (mIsVariantPlaylist) {
return ERROR_MALFORMED;
@@ -203,9 +210,9 @@
if (!line.startsWith("#")) {
if (!mIsVariantPlaylist) {
- int32_t durationSecs;
+ int64_t durationUs;
if (itemMeta == NULL
- || !itemMeta->findInt32("duration", &durationSecs)) {
+ || !itemMeta->findInt64("durationUs", &durationUs)) {
return ERROR_MALFORMED;
}
}
@@ -252,6 +259,30 @@
}
// static
+status_t M3UParser::parseMetaDataDuration(
+ const AString &line, sp<AMessage> *meta, const char *key) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ double x;
+ status_t err = ParseDouble(line.c_str() + colonPos + 1, &x);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (meta->get() == NULL) {
+ *meta = new AMessage;
+ }
+ (*meta)->setInt64(key, (int64_t)x * 1E6);
+
+ return OK;
+}
+
+// static
status_t M3UParser::parseStreamInf(
const AString &line, sp<AMessage> *meta) {
ssize_t colonPos = line.find(":");
@@ -412,4 +443,18 @@
return OK;
}
+// static
+status_t M3UParser::ParseDouble(const char *s, double *x) {
+ char *end;
+ double dval = strtod(s, &end);
+
+ if (end == s || (*end != '\0' && *end != ',')) {
+ return ERROR_MALFORMED;
+ }
+
+ *x = dval;
+
+ return OK;
+}
+
} // namespace android
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
index 63895b4..478582d 100644
--- a/media/libstagefright/include/M3UParser.h
+++ b/media/libstagefright/include/M3UParser.h
@@ -63,6 +63,9 @@
static status_t parseMetaData(
const AString &line, sp<AMessage> *meta, const char *key);
+ static status_t parseMetaDataDuration(
+ const AString &line, sp<AMessage> *meta, const char *key);
+
static status_t parseStreamInf(
const AString &line, sp<AMessage> *meta);
@@ -70,6 +73,7 @@
const AString &line, sp<AMessage> *meta, const AString &baseURI);
static status_t ParseInt32(const char *s, int32_t *x);
+ static status_t ParseDouble(const char *s, double *x);
DISALLOW_EVIL_CONSTRUCTORS(M3UParser);
};
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index ca2578f..1ccf50d 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -109,7 +109,9 @@
void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
void removeActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
void freeActiveBuffers();
-
+ status_t useGraphicBuffer2_l(
+ OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+ OMX::buffer_id *buffer);
static OMX_ERRORTYPE OnEvent(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 78037b97..8f2ea95 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -47,6 +47,7 @@
sp<ANativeWindow> mNativeWindow;
int32_t mWidth, mHeight;
int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+ int32_t mCropWidth, mCropHeight;
SoftwareRenderer(const SoftwareRenderer &);
SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index deecd25..0817bab 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -18,6 +18,7 @@
#define WVM_EXTRACTOR_H_
+#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaExtractor.h>
#include <utils/Errors.h>
@@ -67,6 +68,10 @@
WVMExtractor(const WVMExtractor &);
WVMExtractor &operator=(const WVMExtractor &);
+
+ static Mutex sMutex;
+ static uint32_t sActiveExtractors;
+ static void *sVendorLibHandle;
};
} // namespace android
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 14968e8..d23aa3a 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -21,7 +21,6 @@
#include <dlfcn.h>
#include <sys/prctl.h>
-#include <sys/resource.h>
#include "../include/OMX.h"
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 545e6d4..504d470 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -86,7 +86,11 @@
mPluginByComponentName.add(name8, plugin);
}
- CHECK_EQ(err, OMX_ErrorNoMore);
+
+ if (err != OMX_ErrorNoMore) {
+ LOGE("OMX plugin failed w/ error 0x%08x after registering %d "
+ "components", err, mPluginByComponentName.size());
+ }
}
void OMXMaster::clearPlugins() {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 8462988..12ab941 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -406,12 +406,77 @@
return OK;
}
+status_t OMXNodeInstance::useGraphicBuffer2_l(
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+ OMX::buffer_id *buffer) {
+
+ // port definition
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 0;
+ def.nVersion.s.nRevision = 0;
+ def.nVersion.s.nStep = 0;
+ def.nPortIndex = portIndex;
+ OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
+ if (err != OK)
+ {
+ LOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
+ return err;
+ }
+
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+
+ OMX_BUFFERHEADERTYPE *header = NULL;
+ OMX_U8* bufferHandle = const_cast<OMX_U8*>(
+ reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
+
+ err = OMX_UseBuffer(
+ mHandle,
+ &header,
+ portIndex,
+ bufferMeta,
+ def.nBufferSize,
+ bufferHandle);
+
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+ delete bufferMeta;
+ bufferMeta = NULL;
+ *buffer = 0;
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pBuffer, bufferHandle);
+ CHECK_EQ(header->pAppPrivate, bufferMeta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+// XXX: This function is here for backwards compatibility. Once the OMX
+// implementations have been updated this can be removed and useGraphicBuffer2
+// can be renamed to useGraphicBuffer.
status_t OMXNodeInstance::useGraphicBuffer(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
OMX::buffer_id *buffer) {
Mutex::Autolock autoLock(mLock);
+ // See if the newer version of the extension is present.
OMX_INDEXTYPE index;
+ if (OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
+ &index) == OMX_ErrorNone) {
+ return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
+ }
+
+ LOGW("Falling back to the deprecated useAndroidNativeBuffer support. You "
+ "should switch to the useAndroidNativeBuffer2 extension.");
+
OMX_ERRORTYPE err = OMX_GetExtensionIndex(
mHandle,
const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index a404f1f..d4354db 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -485,24 +485,20 @@
};
static const MimeToURL kMimeToURL[] = {
{ "video/avc",
- "file:///sdcard/media_api/video/H264_AAC.3gp" },
- { "video/mp4v-es", "file:///sdcard/media_api/video/gingerkids.MP4" },
+ "file:///sdcard/media_api/video/H264_500_AAC_128.3gp" },
+ { "video/mp4v-es", "file:///sdcard/media_api/video/MPEG4_320_AAC_64.mp4" },
{ "video/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
{ "audio/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
- { "audio/amr-wb",
- "file:///sdcard/media_api/music/"
- "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
+ { "audio/amr-wb", NULL },
{ "audio/mp4a-latm",
- "file:///sdcard/media_api/video/H264_AAC.3gp" },
+ "file:///sdcard/media_api/video/H263_56_AAC_24.3gp" },
{ "audio/mpeg",
- "file:///sdcard/media_api/music/MP3CBR.mp3" },
- { "audio/vorbis",
- "file:///sdcard/media_api/metaDataTestMedias/OGG/"
- "When You Say Nothing At All.ogg" },
+ "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
+ { "audio/vorbis", NULL },
{ "video/x-vnd.on2.vp8",
- "file:///sdcard/media_api/webm/big-buck-bunny_trailer.webm" },
+ "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
"file:///sdcard/M1F1-mulaw-AFsp.wav" },
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index 9a6062c..59d0e15 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -2,6 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ TextDescriptions.cpp \
TimedTextParser.cpp \
TimedTextPlayer.cpp
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
new file mode 100644
index 0000000..f9c1fe0
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -0,0 +1,385 @@
+/*
+ * 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.
+ */
+
+#include "TextDescriptions.h"
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+TextDescriptions::TextDescriptions() {
+}
+
+status_t TextDescriptions::getParcelOfDescriptions(
+ const uint8_t *data, ssize_t size,
+ uint32_t flags, int timeMs, Parcel *parcel) {
+ parcel->freeData();
+
+ if (flags & IN_BAND_TEXT_3GPP) {
+ if (flags & GLOBAL_DESCRIPTIONS) {
+ return extract3GPPGlobalDescriptions(data, size, parcel, 0);
+ } else if (flags & LOCAL_DESCRIPTIONS) {
+ return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0);
+ }
+ } else if (flags & OUT_OF_BAND_TEXT_SRT) {
+ if (flags & LOCAL_DESCRIPTIONS) {
+ return extractSRTLocalDescriptions(data, size, timeMs, parcel);
+ }
+ }
+
+ return ERROR_UNSUPPORTED;
+}
+
+// Parse the SRT text sample, and store the timing and text sample in a Parcel.
+// The Parcel will be sent to MediaPlayer.java through event, and will be
+// parsed in TimedText.java.
+status_t TextDescriptions::extractSRTLocalDescriptions(
+ const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel) {
+ parcel->writeInt32(KEY_LOCAL_SETTING);
+ parcel->writeInt32(KEY_START_TIME);
+ parcel->writeInt32(timeMs);
+
+ parcel->writeInt32(KEY_STRUCT_TEXT);
+ // write the size of the text sample
+ parcel->writeInt32(size);
+ // write the text sample as a byte array
+ parcel->writeInt32(size);
+ parcel->write(data, size);
+
+ return OK;
+}
+
+// Extract the local 3GPP display descriptions. 3GPP local descriptions
+// are appended to the text sample if any. The descriptions could include
+// information such as text styles, highlights, karaoke and so on. They
+// are contained in different boxes, such as 'styl' box contains text
+// styles, and 'krok' box contains karaoke timing and positions.
+status_t TextDescriptions::extract3GPPLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel, int depth) {
+ if (depth == 0) {
+ parcel->writeInt32(KEY_LOCAL_SETTING);
+
+ // write start time to display this text sample
+ parcel->writeInt32(KEY_START_TIME);
+ parcel->writeInt32(timeMs);
+
+ ssize_t textLen = (*data) << 8 | (*(data + 1));
+
+ // write text sample length and text sample itself
+ parcel->writeInt32(KEY_STRUCT_TEXT);
+ parcel->writeInt32(textLen);
+ parcel->writeInt32(textLen);
+ parcel->write(data + 2, textLen);
+
+ if (size > textLen) {
+ data += (textLen + 2);
+ size -= (textLen + 2);
+ } else {
+ return OK;
+ }
+ }
+
+ const uint8_t *tmpData = data;
+ ssize_t chunkSize = U32_AT(tmpData);
+ uint32_t chunkType = U32_AT(tmpData + 4);
+
+ if (chunkSize <= 0) {
+ return OK;
+ }
+
+ tmpData += 8;
+
+ switch(chunkType) {
+ // 'styl' box specifies the style of the text.
+ case FOURCC('s', 't', 'y', 'l'):
+ {
+ uint16_t count = U16_AT(tmpData);
+
+ tmpData += 2;
+
+ for (int i = 0; i < count; i++) {
+ parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+ parcel->writeInt32(KEY_START_CHAR);
+ parcel->writeInt32(U16_AT(tmpData));
+
+ parcel->writeInt32(KEY_END_CHAR);
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ parcel->writeInt32(KEY_FONT_ID);
+ parcel->writeInt32(U16_AT(tmpData + 4));
+
+ parcel->writeInt32(KEY_STYLE_FLAGS);
+ parcel->writeInt32(*(tmpData + 6));
+
+ parcel->writeInt32(KEY_FONT_SIZE);
+ parcel->writeInt32(*(tmpData + 7));
+
+ parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+ uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+ | *(tmpData + 10) << 8 | *(tmpData + 11);
+ parcel->writeInt32(rgba);
+
+ tmpData += 12;
+ }
+
+ break;
+ }
+ // 'krok' box. The number of highlight events is specified, and each
+ // event is specified by a starting and ending char offset and an end
+ // time for the event.
+ case FOURCC('k', 'r', 'o', 'k'):
+ {
+
+ parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
+
+ int startTime = U32_AT(tmpData);
+ uint16_t count = U16_AT(tmpData + 4);
+ parcel->writeInt32(count);
+
+ tmpData += 6;
+ int lastEndTime = 0;
+
+ for (int i = 0; i < count; i++) {
+ parcel->writeInt32(startTime + lastEndTime);
+
+ lastEndTime = U32_AT(tmpData);
+ parcel->writeInt32(lastEndTime);
+
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ tmpData += 8;
+ }
+
+ break;
+ }
+ // 'hlit' box specifies highlighted text
+ case FOURCC('h', 'l', 'i', 't'):
+ {
+ parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
+
+ // the start char offset to highlight
+ parcel->writeInt32(U16_AT(tmpData));
+ // the last char offset to highlight
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ break;
+ }
+ // 'hclr' box specifies the RGBA color: 8 bits each of
+ // red, green, blue, and an alpha(transparency) value
+ case FOURCC('h', 'c', 'l', 'r'):
+ {
+ parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
+
+ uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
+ | *(tmpData + 2) << 8 | *(tmpData + 3);
+ parcel->writeInt32(rgba);
+
+ break;
+ }
+ // 'dlay' box specifies a delay after a scroll in and/or
+ // before scroll out.
+ case FOURCC('d', 'l', 'a', 'y'):
+ {
+ parcel->writeInt32(KEY_SCROLL_DELAY);
+
+ uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
+ | *(tmpData + 2) << 8 | *(tmpData + 3);
+ parcel->writeInt32(delay);
+
+ break;
+ }
+ // 'href' box for hyper text link
+ case FOURCC('h', 'r', 'e', 'f'):
+ {
+ parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
+
+ // the start offset of the text to be linked
+ parcel->writeInt32(U16_AT(tmpData));
+ // the end offset of the text
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ // the number of bytes in the following URL
+ int len = *(tmpData + 4);
+ parcel->writeInt32(len);
+
+ // the linked-to URL
+ parcel->writeInt32(len);
+ parcel->write(tmpData + 5, len);
+
+ tmpData += (5 + len);
+
+ // the number of bytes in the following "alt" string
+ len = *tmpData;
+ parcel->writeInt32(len);
+
+ // an "alt" string for user display
+ parcel->writeInt32(len);
+ parcel->write(tmpData + 1, len);
+
+ break;
+ }
+ // 'tbox' box to indicate the position of the text with values
+ // of top, left, bottom and right
+ case FOURCC('t', 'b', 'o', 'x'):
+ {
+ parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+ parcel->writeInt32(U16_AT(tmpData));
+ parcel->writeInt32(U16_AT(tmpData + 2));
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ break;
+ }
+ // 'blnk' to specify the char range to be blinked
+ case FOURCC('b', 'l', 'n', 'k'):
+ {
+ parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
+
+ // start char offset
+ parcel->writeInt32(U16_AT(tmpData));
+ // end char offset
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ break;
+ }
+ // 'twrp' box specifies text wrap behavior. If the value if 0x00,
+ // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
+ // 0x02-0xff are reserved.
+ case FOURCC('t', 'w', 'r', 'p'):
+ {
+ parcel->writeInt32(KEY_WRAP_TEXT);
+ parcel->writeInt32(*tmpData);
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ if (size > chunkSize) {
+ data += chunkSize;
+ size -= chunkSize;
+ // continue to parse next box
+ return extract3GPPLocalDescriptions(data, size, 0, parcel, 1);
+ }
+
+ return OK;
+}
+
+// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
+status_t TextDescriptions::extract3GPPGlobalDescriptions(
+ const uint8_t *data, ssize_t size, Parcel *parcel, int depth) {
+
+ ssize_t chunkSize = U32_AT(data);
+ uint32_t chunkType = U32_AT(data + 4);
+ const uint8_t *tmpData = data;
+ tmpData += 8;
+
+ if (size < chunkSize) {
+ return OK;
+ }
+
+ if (depth == 0) {
+ parcel->writeInt32(KEY_GLOBAL_SETTING);
+ }
+ switch(chunkType) {
+ case FOURCC('t', 'x', '3', 'g'):
+ {
+ tmpData += 8; // skip the first 8 bytes
+ parcel->writeInt32(KEY_DISPLAY_FLAGS);
+ parcel->writeInt32(U32_AT(tmpData));
+
+ parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
+ parcel->writeInt32(tmpData[4]);
+ parcel->writeInt32(tmpData[5]);
+
+ parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
+ uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
+ | *(tmpData + 8) << 8 | *(tmpData + 9);
+ parcel->writeInt32(rgba);
+
+ tmpData += 10;
+ parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+ parcel->writeInt32(U16_AT(tmpData));
+ parcel->writeInt32(U16_AT(tmpData + 2));
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ tmpData += 8;
+ parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+ parcel->writeInt32(KEY_START_CHAR);
+ parcel->writeInt32(U16_AT(tmpData));
+
+ parcel->writeInt32(KEY_END_CHAR);
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ parcel->writeInt32(KEY_FONT_ID);
+ parcel->writeInt32(U16_AT(tmpData + 4));
+
+ parcel->writeInt32(KEY_STYLE_FLAGS);
+ parcel->writeInt32(*(tmpData + 6));
+
+ parcel->writeInt32(KEY_FONT_SIZE);
+ parcel->writeInt32(*(tmpData + 7));
+
+ parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+ rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+ | *(tmpData + 10) << 8 | *(tmpData + 11);
+ parcel->writeInt32(rgba);
+
+ tmpData += 12;
+ parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+ uint16_t count = U16_AT(tmpData);
+ parcel->writeInt32(count);
+
+ tmpData += 2;
+ for (int i = 0; i < count; i++) {
+ // font ID
+ parcel->writeInt32(U16_AT(tmpData));
+
+ // font name length
+ parcel->writeInt32(*(tmpData + 2));
+
+ int len = *(tmpData + 2);
+
+ parcel->write(tmpData + 3, len);
+ tmpData += 3 + len;
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ data += chunkSize;
+ size -= chunkSize;
+
+ if (size > 0) {
+ // continue to extract next 'tx3g'
+ return extract3GPPGlobalDescriptions(data, size, parcel, 1);
+ }
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/TextDescriptions.h
new file mode 100644
index 0000000..01449175
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.h
@@ -0,0 +1,84 @@
+ /*
+ * 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.
+ */
+
+#ifndef TEXT_DESCRIPTIONS_H_
+
+#define TEXT_DESCRIPTIONS_H_
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class TextDescriptions {
+public:
+ enum {
+ IN_BAND_TEXT_3GPP = 0x01,
+ OUT_OF_BAND_TEXT_SRT = 0x02,
+
+ GLOBAL_DESCRIPTIONS = 0x100,
+ LOCAL_DESCRIPTIONS = 0x200,
+ };
+
+ static status_t getParcelOfDescriptions(
+ const uint8_t *data, ssize_t size,
+ uint32_t flags, int timeMs, Parcel *parcel);
+private:
+ TextDescriptions();
+
+ enum {
+ // These keys must be in sync with the keys in TimedText.java
+ KEY_DISPLAY_FLAGS = 1, // int
+ KEY_STYLE_FLAGS = 2, // int
+ KEY_BACKGROUND_COLOR_RGBA = 3, // int
+ KEY_HIGHLIGHT_COLOR_RGBA = 4, // int
+ KEY_SCROLL_DELAY = 5, // int
+ KEY_WRAP_TEXT = 6, // int
+ KEY_START_TIME = 7, // int
+ KEY_STRUCT_BLINKING_TEXT_LIST = 8, // List<CharPos>
+ KEY_STRUCT_FONT_LIST = 9, // List<Font>
+ KEY_STRUCT_HIGHLIGHT_LIST = 10, // List<CharPos>
+ KEY_STRUCT_HYPER_TEXT_LIST = 11, // List<HyperText>
+ KEY_STRUCT_KARAOKE_LIST = 12, // List<Karaoke>
+ KEY_STRUCT_STYLE_LIST = 13, // List<Style>
+ KEY_STRUCT_TEXT_POS = 14, // TextPos
+ KEY_STRUCT_JUSTIFICATION = 15, // Justification
+ KEY_STRUCT_TEXT = 16, // Text
+
+ KEY_GLOBAL_SETTING = 101,
+ KEY_LOCAL_SETTING = 102,
+ KEY_START_CHAR = 103,
+ KEY_END_CHAR = 104,
+ KEY_FONT_ID = 105,
+ KEY_FONT_SIZE = 106,
+ KEY_TEXT_COLOR_RGBA = 107,
+ };
+
+ static status_t extractSRTLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel);
+ static status_t extract3GPPGlobalDescriptions(
+ const uint8_t *data, ssize_t size,
+ Parcel *parcel, int depth);
+ static status_t extract3GPPLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel, int depth);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions);
+};
+
+} // namespace android
+#endif // TEXT_DESCRIPTIONS_H_
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index 50bb16d..7c8a747 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
+
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
@@ -27,9 +28,11 @@
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/Utils.h>
+
#include "include/AwesomePlayer.h"
#include "TimedTextPlayer.h"
#include "TimedTextParser.h"
+#include "TextDescriptions.h"
namespace android {
@@ -92,10 +95,11 @@
return BAD_VALUE;
}
+ status_t err;
if (index < mTextTrackVector.size()) { // start an in-band text
mSource = mTextTrackVector.itemAt(index);
- status_t err = mSource->start();
+ err = mSource->start();
if (err != OK) {
return err;
@@ -112,13 +116,17 @@
mTextParser = new TimedTextParser();
}
- status_t err;
if ((err = mTextParser->init(mOutOfBandSource, fileType)) != OK) {
return err;
}
mTextType = kOutOfBandText;
}
+ // send sample description format
+ if ((err = extractAndSendGlobalDescriptions()) != OK) {
+ return err;
+ }
+
int64_t positionUs;
mObserver->getPosition(&positionUs);
seekTo(positionUs);
@@ -211,21 +219,17 @@
}
mTextEventPending = false;
+ if (mData.dataSize() > 0) {
+ notifyListener(MEDIA_TIMED_TEXT, &mData);
+ mData.freeData();
+ }
+
MediaSource::ReadOptions options;
if (mSeeking) {
options.setSeekTo(mSeekTimeUs,
MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
mSeeking = false;
- if (mTextType == kInBandText) {
- if (mTextBuffer != NULL) {
- mTextBuffer->release();
- mTextBuffer = NULL;
- }
- } else {
- mText.clear();
- }
-
notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen
}
@@ -233,32 +237,12 @@
mObserver->getPosition(&positionUs);
if (mTextType == kInBandText) {
- if (mTextBuffer != NULL) {
- uint8_t *tmp = (uint8_t *)(mTextBuffer->data());
- size_t len = (*tmp) << 8 | (*(tmp + 1));
-
- notifyListener(MEDIA_TIMED_TEXT,
- tmp + 2,
- len);
-
- mTextBuffer->release();
- mTextBuffer = NULL;
-
- }
-
if (mSource->read(&mTextBuffer, &options) != OK) {
return;
}
mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
} else {
- if (mText.size() > 0) {
- notifyListener(MEDIA_TIMED_TEXT,
- mText.c_str(),
- mText.size());
- mText.clear();
- }
-
int64_t endTimeUs;
if (mTextParser->getText(
&mText, &timeUs, &endTimeUs, &options) != OK) {
@@ -266,6 +250,19 @@
}
}
+ if (timeUs > 0) {
+ extractAndAppendLocalDescriptions(timeUs);
+ }
+
+ if (mTextType == kInBandText) {
+ if (mTextBuffer != NULL) {
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+ }
+ } else {
+ mText.clear();
+ }
+
//send the text now
if (timeUs <= positionUs + 100000ll) {
postTextEvent();
@@ -297,7 +294,8 @@
Mutex::Autolock autoLock(mLock);
if (key == KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE) {
- String8 uri = request.readString8();
+ const String16 uri16 = request.readString16();
+ String8 uri = String8(uri16);
KeyedVector<String8, String8> headers;
// To support local subtitle file only for now
@@ -327,21 +325,92 @@
return INVALID_OPERATION;
}
-void TimedTextPlayer::notifyListener(
- int msg, const void *data, size_t size) {
+void TimedTextPlayer::notifyListener(int msg, const Parcel *parcel) {
if (mListener != NULL) {
sp<MediaPlayerBase> listener = mListener.promote();
if (listener != NULL) {
- if (size > 0) {
- mData.freeData();
- mData.write(data, size);
-
- listener->sendEvent(msg, 0, 0, &mData);
+ if (parcel && (parcel->dataSize() > 0)) {
+ listener->sendEvent(msg, 0, 0, parcel);
} else { // send an empty timed text to clear the screen
listener->sendEvent(msg);
}
}
}
}
+
+// Each text sample consists of a string of text, optionally with sample
+// modifier description. The modifier description could specify a new
+// text style for the string of text. These descriptions are present only
+// if they are needed. This method is used to extract the modifier
+// description and append it at the end of the text.
+status_t TimedTextPlayer::extractAndAppendLocalDescriptions(int64_t timeUs) {
+ const void *data;
+ size_t size = 0;
+ int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
+
+ if (mTextType == kInBandText) {
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+ data = mTextBuffer->data();
+ size = mTextBuffer->size();
+ } else {
+ // support 3GPP only for now
+ return ERROR_UNSUPPORTED;
+ }
+ } else {
+ data = mText.c_str();
+ size = mText.size();
+ flag |= TextDescriptions::OUT_OF_BAND_TEXT_SRT;
+ }
+
+ if ((size > 0) && (flag != TextDescriptions::LOCAL_DESCRIPTIONS)) {
+ mData.freeData();
+ return TextDescriptions::getParcelOfDescriptions(
+ (const uint8_t *)data, size, flag, timeUs / 1000, &mData);
+ }
+
+ return OK;
+}
+
+// To extract and send the global text descriptions for all the text samples
+// in the text track or text file.
+status_t TimedTextPlayer::extractAndSendGlobalDescriptions() {
+ const void *data;
+ size_t size = 0;
+ int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS;
+
+ if (mTextType == kInBandText) {
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+ // support 3GPP only for now
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ uint32_t type;
+ // get the 'tx3g' box content. This box contains the text descriptions
+ // used to render the text track
+ if (!mSource->getFormat()->findData(
+ kKeyTextFormatData, &type, &data, &size)) {
+ return ERROR_MALFORMED;
+ }
+
+ flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+ }
+ }
+
+ if ((size > 0) && (flag != TextDescriptions::GLOBAL_DESCRIPTIONS)) {
+ Parcel parcel;
+ if (TextDescriptions::getParcelOfDescriptions(
+ (const uint8_t *)data, size, flag, 0, &parcel) == OK) {
+ if (parcel.dataSize() > 0) {
+ notifyListener(MEDIA_TIMED_TEXT, &parcel);
+ }
+ }
+ }
+
+ return OK;
+}
}
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h
index 590760b..a744db5 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.h
+++ b/media/libstagefright/timedtext/TimedTextPlayer.h
@@ -103,8 +103,10 @@
void postTextEvent(int64_t delayUs = -1);
void cancelTextEvent();
- void notifyListener(
- int msg, const void *data = NULL, size_t size = 0);
+ void notifyListener(int msg, const Parcel *parcel = NULL);
+
+ status_t extractAndAppendLocalDescriptions(int64_t timeUs);
+ status_t extractAndSendGlobalDescriptions();
DISALLOW_EVIL_CONSTRUCTORS(TimedTextPlayer);
};
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 4a8fd3e..bc04e8c 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -95,10 +95,11 @@
MTP_EVENT_STORE_REMOVED,
};
-MtpServer::MtpServer(int fd, MtpDatabase* database,
+MtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp,
int fileGroup, int filePerm, int directoryPerm)
: mFD(fd),
mDatabase(database),
+ mPtp(ptp),
mFileGroup(fileGroup),
mFilePermission(filePerm),
mDirectoryPermission(directoryPerm),
@@ -426,9 +427,20 @@
// fill in device info
mData.putUInt16(MTP_STANDARD_VERSION);
- mData.putUInt32(6); // MTP Vendor Extension ID
+ if (mPtp) {
+ mData.putUInt32(0);
+ } else {
+ // MTP Vendor Extension ID
+ mData.putUInt32(6);
+ }
mData.putUInt16(MTP_STANDARD_VERSION);
- string.set("microsoft.com: 1.0; android.com: 1.0;");
+ if (mPtp) {
+ // no extensions
+ string.set("");
+ } else {
+ // MTP extensions
+ string.set("microsoft.com: 1.0; android.com: 1.0;");
+ }
mData.putString(string); // MTP Extensions
mData.putUInt16(0); //Functional Mode
mData.putAUInt16(kSupportedOperationCodes,
@@ -533,12 +545,10 @@
MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
- // 0x00000000 for all objects?
+ // 0x00000000 for all objects
if (!hasStorage(storageID))
return MTP_RESPONSE_INVALID_STORAGE_ID;
- if (parent == 0xFFFFFFFF)
- parent = 0;
MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
mData.putAUInt32(handles);
@@ -552,11 +562,9 @@
MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
- // 0x00000000 for all objects?
+ // 0x00000000 for all objects
if (!hasStorage(storageID))
return MTP_RESPONSE_INVALID_STORAGE_ID;
- if (parent == 0xFFFFFFFF)
- parent = 0;
int count = mDatabase->getNumObjects(storageID, format, parent);
if (count >= 0) {
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 859a18e..dfa8258 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -39,6 +39,9 @@
MtpDatabase* mDatabase;
+ // appear as a PTP device
+ bool mPtp;
+
// group to own new files and folders
int mFileGroup;
// permissions for new files and directories
@@ -87,7 +90,7 @@
Vector<ObjectEdit*> mObjectEditList;
public:
- MtpServer(int fd, MtpDatabase* database,
+ MtpServer(int fd, MtpDatabase* database, bool ptp,
int fileGroup, int filePerm, int directoryPerm);
virtual ~MtpServer();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 0dadaa5..5120694 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -1334,7 +1334,14 @@
// TODO : remove TC_API_035
@LargeTest
public void testEffectKenBurn() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+ // Test ken burn effect using a JPEG file.
+ testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg");
+
+ // Test ken burn effect using a PNG file
+ testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png");
+ }
+
+ private void testEffectKenBurn(final String imageItemFileName) throws Exception {
final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
final MediaImageItem mediaImageItem =
mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
@@ -1350,11 +1357,14 @@
final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
- assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
+ assertNotNull("EffectKenBurns: " + imageItemFileName,
+ kbEffectOnMediaItem);
+
mediaImageItem.addEffect(kbEffectOnMediaItem);
- assertEquals("KenBurn Start Rect", startRect,
+ assertEquals("KenBurn Start Rect: " + imageItemFileName, startRect,
kbEffectOnMediaItem.getStartRect());
- assertEquals("KenBurn End Rect", endRect,
+
+ assertEquals("KenBurn End Rect: " + imageItemFileName, endRect,
kbEffectOnMediaItem.getEndRect());
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
index 38f598a..bfa3976 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerMetadataParserTest.java
@@ -277,11 +277,17 @@
// getBoolean
@SmallTest
public void testGetBoolean() throws Exception {
- writeBooleanRecord(Metadata.DRM_CRIPPLED, true);
+ writeBooleanRecord(Metadata.PAUSE_AVAILABLE, true);
+ writeBooleanRecord(Metadata.SEEK_AVAILABLE, true);
+ writeBooleanRecord(Metadata.SEEK_BACKWARD_AVAILABLE, true);
+ writeBooleanRecord(Metadata.SEEK_FORWARD_AVAILABLE, true);
adjustSize();
assertParse();
- assertEquals(true, mMetadata.getBoolean(Metadata.DRM_CRIPPLED));
+ assertEquals(true, mMetadata.getBoolean(Metadata.PAUSE_AVAILABLE));
+ assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_AVAILABLE));
+ assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE));
+ assertEquals(true, mMetadata.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE));
}
// getLong
@@ -329,19 +335,6 @@
assertEquals(new Date(0), mMetadata.getDate(Metadata.DATE));
}
- // getTimedText
- @SmallTest
- public void testGetTimedText() throws Exception {
- Date now = Calendar.getInstance().getTime();
- writeTimedTextRecord(Metadata.CAPTION, now.getTime(),
- 10, "Some caption");
- adjustSize();
- assertParse();
-
- Metadata.TimedText caption = mMetadata.getTimedText(Metadata.CAPTION);
- assertEquals("" + now + "-" + 10 + ":Some caption", caption.toString());
- }
-
// ----------------------------------------------------------------------
// HELPERS TO APPEND RECORDS
// ----------------------------------------------------------------------
@@ -416,17 +409,4 @@
mParcel.writeString(tz);
adjustSize(start);
}
-
- // Insert a TimedText record at the current position.
- private void writeTimedTextRecord(int metadataId, long begin,
- int duration, String text) {
- final int start = mParcel.dataPosition();
- mParcel.writeInt(-1); // Placeholder for the length
- mParcel.writeInt(metadataId);
- mParcel.writeInt(Metadata.TIMED_TEXT_VAL);
- mParcel.writeLong(begin);
- mParcel.writeInt(duration);
- mParcel.writeString(text);
- adjustSize(start);
- }
}
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 26cac50..0d8ea28 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -404,7 +404,6 @@
AMOTION_EVENT_BUTTON_TERTIARY = 1 << 2,
AMOTION_EVENT_BUTTON_BACK = 1 << 3,
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
- AMOTION_EVENT_BUTTON_ERASER = 1 << 5,
};
/*
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 7775dbf..e0c38b1 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -18,7 +18,6 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.nfc.ApduList;
import android.nfc.INfcAdapterExtras;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
@@ -207,4 +206,21 @@
public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
return sEmbeddedEe;
}
+
+ /**
+ * Authenticate the client application.
+ *
+ * Some implementations of NFC Adapter Extras may require applications
+ * to authenticate with a token, before using other methods.
+ *
+ * @param a implementation specific token
+ * @throws a {@link java.lang.SecurityException} if authentication failed
+ */
+ public void authenticate(byte[] token) {
+ try {
+ sService.authenticate(token);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
}
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
index eb2f6f8..63c2de2 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -55,6 +55,64 @@
*/
public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
+ /**
+ * Broadcast action: A filtered APDU was received.
+ *
+ * <p>This happens when an APDU of interest was matched by the Nfc adapter,
+ * for instance as the result of matching an externally-configured filter.
+ *
+ * <p>The filter configuration mechanism is not currently defined.
+ *
+ * <p>Always contains the extra field {@link EXTRA_APDU_BYTES}.
+ *
+ * @hide
+ */
+ public static final String ACTION_APDU_RECEIVED =
+ "com.android.nfc_extras.action.APDU_RECEIVED";
+
+ /**
+ * Mandatory byte array extra field in {@link #ACTION_APDU_RECEIVED}.
+ *
+ * <p>Contains the bytes of the received APDU.
+ *
+ * @hide
+ */
+ public static final String EXTRA_APDU_BYTES =
+ "com.android.nfc_extras.extra.APDU_BYTES";
+
+ /**
+ * Broadcast action: An EMV card removal event was detected.
+ *
+ * @hide
+ */
+ public static final String ACTION_EMV_CARD_REMOVAL =
+ "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
+
+ /**
+ * Broadcast action: An adapter implementing MIFARE Classic via card
+ * emulation detected that a block has been accessed.
+ *
+ * <p>This may only be issued for the first block that the reader
+ * authenticates to.
+ *
+ * <p>May contain the extra field {@link #EXTRA_MIFARE_BLOCK}.
+ *
+ * @hide
+ */
+ public static final String ACTION_MIFARE_ACCESS_DETECTED =
+ "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
+
+ /**
+ * Optional integer extra field in {@link #ACTION_MIFARE_ACCESS_DETECTED}.
+ *
+ * <p>Provides the block number being accessed. If not set, the block
+ * number being accessed is unknown.
+ *
+ * @hide
+ */
+ public static final String EXTRA_MIFARE_BLOCK =
+ "com.android.nfc_extras.extra.MIFARE_BLOCK";
+
NfcExecutionEnvironment(NfcAdapterExtras extras) {
mExtras = extras;
}
diff --git a/packages/DefaultContainerService/res/values-af/strings.xml b/packages/DefaultContainerService/res/values-af/strings.xml
new file mode 100644
index 0000000..5fa075b
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-af/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name" msgid="4841491635055379553">"Pakkettoegangshelper"</string>
+</resources>
diff --git a/packages/DefaultContainerService/res/values-ms/strings.xml b/packages/DefaultContainerService/res/values-ms/strings.xml
new file mode 100644
index 0000000..77d7927
--- /dev/null
+++ b/packages/DefaultContainerService/res/values-ms/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+**
+** Copyright 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="service_name" msgid="4841491635055379553">"Pembantu Akses Pakej"</string>
+</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 0c4ef7d..9469601 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -531,7 +531,12 @@
private void restoreFileData(String filename, BackupDataInput data) {
byte[] bytes = new byte[data.getDataSize()];
if (bytes.length <= 0) return;
- restoreFileData(filename, bytes, bytes.length);
+ try {
+ data.readEntityData(bytes, 0, data.getDataSize());
+ restoreFileData(filename, bytes, bytes.length);
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read file data for " + filename);
+ }
}
private void restoreFileData(String filename, byte[] bytes, int size) {
@@ -589,7 +594,12 @@
private void restoreWifiSupplicant(String filename, BackupDataInput data) {
byte[] bytes = new byte[data.getDataSize()];
if (bytes.length <= 0) return;
- restoreWifiSupplicant(filename, bytes, bytes.length);
+ try {
+ data.readEntityData(bytes, 0, data.getDataSize());
+ restoreWifiSupplicant(filename, bytes, bytes.length);
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to read supplicant data");
+ }
}
private void restoreWifiSupplicant(String filename, byte[] bytes, int size) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 55f5280..6d8eab6 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -25,6 +25,10 @@
android:exported="true"
/>
+ <activity android:name=".usb.UsbPreferenceActivity"
+ android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:excludeFromRecents="true">
+ </activity>
<activity android:name=".usb.UsbStorageActivity"
android:excludeFromRecents="true">
</activity>
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
index bc127bd..a90c412 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
index 59af804..9d6032c 100644
--- a/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
index 2c7a0d4..caa8795 100644
--- a/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-hdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
index baafed6..6f456f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
index 175197b..e592ae6 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
index ec1feff..c1f87a7 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
index c1f9a0f..2d16eda 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
index 0ea3f40..0749413 100644
--- a/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_off.png b/packages/SystemUI/res/drawable-hdpi/hd_off.png
new file mode 100644
index 0000000..e7246cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/hd_on.png b/packages/SystemUI/res/drawable-hdpi/hd_on.png
new file mode 100644
index 0000000..5360d42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
index ff34a7f..cbd72fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
index eb783df..2c48c97 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
index c3e381e..165fa80 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
index d6c8a21..fd33ef3 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..a557164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
index 728a25d..7096b73 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..48cab60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..000af5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
index ca8656c..ac5a97b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..c345e84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
index a4f4e87..a5a9652 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..e77dfafb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
index 299a0e7..e72fde8 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..b91be07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
index 029ea22..31e747e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..5736d46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
index 06c9921..a90dc9b 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..d686787
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..7dfbc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..8883601
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
index 2249d01..2e5dc3c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
index ca3bb5d..a8f4daa 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
index cb938fe..d23f9b7 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6d99ba5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..13b969c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..25e7e6f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
index 47b4ba2..2a94b5d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
index b2c4d45..cb3c433 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..11ddf00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..da512e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..f2a7c6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
index 20d28da..6208581 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..18fe5be
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
index 7cb2643..ab581a1 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..0246cd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
index 3be2eef..bec75e5 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
index 88ac760..fe4d318 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
new file mode 100644
index 0000000..d5503f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
new file mode 100644
index 0000000..a8f2236
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
new file mode 100644
index 0000000..b7ad39c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
index 0c40c73..c93bd8c 100644
--- a/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
new file mode 100644
index 0000000..1680887
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
new file mode 100644
index 0000000..b436fc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
index fcf4417..ce48e0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
index af36ac7..f10a487 100644
--- a/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-hdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
index 18bd8b4..55f6aa1 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
index 993ccf4..19dae07 100644
--- a/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
new file mode 100644
index 0000000..8811df5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
index f313ffb..0c12103 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
index 37b5fef..8fbe78e 100644
--- a/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
index 4ec771a..ddbd3d7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
old mode 100755
new mode 100644
index 2ea2609..2fa0293
--- a/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..4cabd9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..3d1e89d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..8a77137
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..dbfcfda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..cb7a692
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8d1b95c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..4d2b2f5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..aafc621
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..b6c7450
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..67eaebd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..14450ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..0578085
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..12a7ca8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8ac90236
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4debc5f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..92069c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..290e34b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
index c9704fc..2538ab8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
index b37dd9f..cfc6344 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
index 818e292..02757b1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
index 95866b1..4bfb8f2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
index 1aea612..ff4e040 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
index 016b30b..71050c8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
index ec672eb..aa25d50 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
old mode 100755
new mode 100644
index 27bab73..5641b7a
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..a6b0762
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
index 0e6849b..6af7f65 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
index a86a324..29d8f7b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
index 425535e..e80265c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
index 24902d6..c7ff314 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
index 4160a95..2396c01 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
index d459ee3..5256041 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
index 7b64751..5d728e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
index d82930c..4b0472a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
index fcad363..b216c2a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
old mode 100755
new mode 100644
index 8096846..d184206
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
index e94e146..fd2d6c1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
index 8805a40..80ceea0 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
index 07545d5..cdfa661 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
index 7629cef..c8bd44f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
index 4ff7db3..ecdd61f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
index 28578c6..c7c6a92 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
index d9f7a30..795e610 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
index 505ccd4..3b012cd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
index 783c2b6..ca435ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
index 001eaea..63823be 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
index 2c4a07f..b16455f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
index cbae7dc..db44420 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
index 11f3a5c..d99b977 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
index eb42294..72e5d5c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
index 66fb60e..3405e1c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
index 07ea499..940be0f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
index 879c703..199e021 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
index e39767a..50cbbba 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
index 47c1fca..c571496 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
old mode 100755
new mode 100644
index ac80dce..1920d0d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
index 61a7503..466c84c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
index f88091b..2226bab 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
index 95bb3cd..200b9a9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
index c5edf2c..5a592e3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
index 0ef4701..db40781 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
index 31b926b..6bf4841 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
old mode 100755
new mode 100644
index ed02984..f323073
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
index 0ee5b08..2650479 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
index cac7802..d00f2af 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
index ddf88be..a60e4e7 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
index df6e195..00d9149 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
index 4a2f867..cddd68c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
old mode 100755
new mode 100644
index 2b4628f..e43e1a9
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
index 765cdd7..5503df1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
index a0e59cf..081233b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
index 1ef75d3..b30b240 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
index a7dc07e..d018f95 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
index f1f4c4e..c4f34cb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
index 918a476..abdb7a6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
index 6e34e66..f4806cc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
index 5b2acc6..67aeef6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
index 3664ab4..fea1863 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
index f1ff548..1bd644c 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
index b4fa481..46881b2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
index 5a741bb..3dfb469 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
index 7ff375a..2506e58 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
index c8ddfce..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
index 245677b..67f16b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
index 6b6a6df..a59c844 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
index d17771e..2aeb84a 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
index b16e436..48f6122 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index b595b60..4811a30 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
index 76332c1..1439ece 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
index 0bd3ba3..3c25920 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
index 3b8aff4..06c3369 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..cac47a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 473c74a..6d115b9 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
index 54e02b5..a1a712f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
index ccd32fe..43803e4 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
index 046c9a0..313f0f5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 047e888..bff9fac 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
index 21f90b0..75def49 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
index 80f5701..8316842 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
index 1456eea..efbd535 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..fabcd91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 3b8fb13..6f2402d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
index a2675e9..e0dca0b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
index 9a6532a..0968cdd 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
index 96a205f4..54ee2e6 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..c5301a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..36b7327
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
index 52e8a8e..a21c7ce 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..931997e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..54c0a07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
index a7a3623..afec31d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
index 6429ffc6..fa8ab31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
index 03d2147..686158b 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
index 9416793..0ec7307 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..4d29193
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
index 4e161c6..a2aadd92 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
index c8cba34..8349da5 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
index c0de67d..f06e5d1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
index 1647b21..c390437 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
index f5b07e6..20cf07f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
index fbb31b8..f11b58e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
index c6267a4..76170a8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
index c1f2f97..15b0992 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 5e42b55..97d35f3 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
index 8721d5c..8bea46d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
index bd400b5..17423d2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
old mode 100755
new mode 100644
index b8feac6..6d3151d
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 4dab171..ae58b57 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
index 6854a2b..ad1245e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
index 9c868f1..00e5bb8 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
old mode 100755
new mode 100644
index efff76c..cb67d57
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
index e3a3cec..b036a89 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
index 3a5c7e2..117ac31 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
index b9ba6d5..bdae6fb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
old mode 100755
new mode 100644
index dc1ce8e..df34c27
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
index 0ad77f1..2b7d95f 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index 87d1944..6e5f131 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
new file mode 100644
index 0000000..017145e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
new file mode 100644
index 0000000..7466d1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
new file mode 100644
index 0000000..772f77d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
index a933833..6eaf6c9 100644
--- a/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
index 70f7cc2..da1b637 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
index e6dab63..374873c 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/app_icon.png b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..61a3f87
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..b6aca49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..226aaac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
index 1629575..0809456 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
index e87bcec..0e8ec073 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
index fd44002..f9d2737 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
index e455ad6..f5b2c9a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
index 6613585..eb1b18a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
index 7502a54..1abe28a 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
index 5f88279..e896cbb 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
index 8c04bd61..b44123c 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
index 1309176..d0cc5794e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
index 810714e..903b03e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
index 72176ba..9578a218 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
index 82a2bf0..c5e5cda 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
index 1e6c604..0730e3e 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
index 13aee06..eafed59 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
index 76c48a8..ea66c75 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
index 39dfcd3..4db62e3 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
index e78d872..69a6ce6d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
index 456d0b6..6f59975 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
index ad73252..2b593d1 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
index d02de5b..ef4cac8 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
index cb13b91..db42b0d 100644
--- a/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/app_icon.png b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
index 73cdabe..a885aab 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
index b5a39cc..32f08c8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
index 6de880c..0111893 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
index 2dbbfc0..a9c547e 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
index a45f011..6801953 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
index 517a6bb..3ae2537 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
index 821d00e..8a9f2e2 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
index 4cdce84..8c5c482 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
index 5226c1c..36c2cf8 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
index a845648..aee1eed 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
index 1d15587..30884a96 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
index 52d5736..ce91aa9 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
index 79a2a05..82a4f61 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
index b032594..55b6b38 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
index c4abcc9..519154d 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
index f50c987..795c6e1 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
index 1fff17e..b7f5346 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
index 5a2662a..b28bf04 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
index e27439e..2722c21 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
index 8b53f0f..596cae5 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
index a23ec6e..50476ad 100644
--- a/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-large-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a39e5e0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..ffe4546
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..a78cd14
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a43ba99
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..cfeb769
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..b39d233
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..41fd66c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..745717b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..1deb1f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..2dce223
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..e13e73f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..6c9193b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..e9bb9c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-large-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
index 258de13..b94b144 100644
--- a/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/alert_bar_background_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
index 7417afc..3de53d8 100644
--- a/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
+++ b/packages/SystemUI/res/drawable-mdpi/battery_low_battery.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..9b59b05 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..b517af6 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..019f33a 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..6ce1bd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..0633543 100644
--- a/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_off.png b/packages/SystemUI/res/drawable-mdpi/hd_off.png
index ad09eef..6c01b8a 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_off.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/hd_on.png b/packages/SystemUI/res/drawable-mdpi/hd_on.png
index 1471c13..de878ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/hd_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/hd_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
index b08ad3b..7651331 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
index 3f88968..8a4ef86 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
index e0f67e8..ba0ca70 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
index 1a3063c4..667b13d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notification_overlay.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..6d8b923
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
index f8d7008..c33271b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..2ed5df4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..c877f72
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
index 91fd0e8..5ab09f0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..d63b42a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
index 7b54daf..14d1ca9 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..14d437e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
index 55b767f..4dbca6d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..91e1429
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
index 1e39fdc..08d60d1 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..77924f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
index accdcfd..62ca427 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..74d2590
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..1b884ed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..e5711eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
index 7d381dd..45183b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
index 954621b..8169fba 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
index 0d58c3a..6d4d55d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..6619393
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..c046f58
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..6b72be2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
index 7928104..238df06 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
index 88f0a44..ff698fb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..6cc8031
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..540af65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..268a9bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
index d338fc0..2536d92 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..06e09e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
index c888c21..897d216 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..a11dabb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
index 70f72fa..16215bd 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
index f2d0cd9..44e3577 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
index 22d6c79..8725e58 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
index 24166da..f7225ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_bg_protect.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
index 2266d15..2dcb659 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_normal.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
index 4fb1cf1..e7ed68b 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_clock_bg_pressed.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
index b389a35..e346167 100644
--- a/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/notify_panel_notify_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
index abde010..3370aeb 100644
--- a/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
+++ b/packages/SystemUI/res/drawable-mdpi/pocket_drag_pattern.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
index 4dfa3d9..33eabb2 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_overlay.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
index ad025f5..5da42a3 100644
--- a/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
+++ b/packages/SystemUI/res/drawable-mdpi/recent_rez_border.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
index 7e679ed..2b8768b 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
index 621e980..0672564 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_control_holo.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
index baf70cd..511d5c3 100644
--- a/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
index 9cbd9fe..d9598ae 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_handlebar.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
index fa9a90c..761ef05 100644
--- a/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/shade_header_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
index 3a50987..364cf75 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
index 5bde4e5..d7a48f2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_notify_more.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..95a797d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6184516
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..cfbdb09
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..218a0a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..6072855
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..fdfbd33
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..99f9120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..7903132
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..ec514af
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..3ef6ce4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..cd748efe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..5cbc673
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..2005d00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e94765e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..31b1b25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f06e81f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..b544180
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
index f615835..44b4272 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
index f784e7e..83edad5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
index c77e61e..24fd220 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
index b9f721a..a409313 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
index cff969e..d4f75cb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
index d2d7ab3..115ea1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
index 83ce6d0..13b1c23 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
index abe511f..400869e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..6234c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
index d685af8..cde53f5 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
index 8c697a1..9e1f8dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
index 9a4b807..13d9ae3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
index eb11d04..e53ddac 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
index 6e54de0..3146ebf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
index 5bfb33b..432bb20 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
index 119067b..50756bc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
index a70cc2e..f8c4a65 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
index ea3dba7..a278ed9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
index 53221b9..14b2a21 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
index 11d44d0..8072951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
index 9defd79..da4e7bb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
index 136576d..68330a9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
index 26ca31f..c65b1616 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
index de8c5ee..a26a05e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
index 64dbf3c..afae625 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
index 34923fb..1f88c31 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
index 506b5c6..d2a5340 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
index 163976f..9f0941a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
index a6af649..c568da6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
index 0c08e52..c22ae56 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
index 1d02edb..345f351 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
index edc9536..4f931e0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
index 8376817..2897ddb 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
index ecef547..0a58322 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
index a7c48b6..3a9af15 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
index f4bcd9a..260634a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
index b46bb3a..2521f00 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
index e8b70f2..441af6e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
index 4e23c4e..65a74aa 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
index ced9175..addfcf2 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
index 92d4a19..b87ce50 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
index a208736..9b8e776 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
index f407bc9..6a3c498 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
index 5bf6aca..07c9218 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
index b8a65c2..c612b94 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
index a978b68..7c66e93 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
index 710dd52..c76490a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
index a7b35e4..a2fff6f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
index bb05449..1259050 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
index a144222..bd08b97 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
index b0eafb6..0c3c0ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
index f6b83d0..40e6f7e3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
index c9da7b9..81c0c10 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
index bb41db0..6ac52f9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
index 7f6fa9c..f8c4b81 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
index ca20839..d5a768c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
index 1ad5d8b..a697fa6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
index 6eba560..018c951 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
index f2358dd..95b5d3d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
index 1ebe23e..922790e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
index 468ad7d..df74fc3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
index d9f2a0d..2a527c9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
index 290822a..bf88418 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
index e0a3141..8e04b25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
index 116b8e2..44bd99f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
old mode 100755
new mode 100644
index 827d84a..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
old mode 100755
new mode 100644
index d62502d..436f16d
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
old mode 100755
new mode 100644
index edc6023..876d9ee
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
index 3aa22f5..d52cb1a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index 9216030..0cfdca0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index 1afd107..4b805c4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
index 0de5760..7bbfbd1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
index 3af5991..ef8ac73 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
index e042696..60b75ef 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
index 25ca124..632127a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index 49b0175..0b48667 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
index 88b08c8..0fba69d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
index 496df52..b0182a0 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
index 940adf0..da8a957 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index fab2e10..db75f745 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
index 3f4dedd..e19bf64 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
index ff474b6..9e22573 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
index 83045ce..8387514 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
index 2725ed2..a0c3bc7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 409bb31..504990e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
index f5c0aa3..35f7741 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
index 38c7f07..d35736e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
index 429e818..a8820e9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
index ade3716..3416151 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
index 83cb820..435d25d 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
index 174d65c..0e1964c 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
index 9c3c44c..68f4530 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
index 08b975a..584e703 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
index 5799ad2..b114fea 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
index ec617d7..de3f56f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
index 5d9957a..b65df27 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
index 1260c59..7f7074e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
index ae9dc40..2b4af59 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
index ed157a8..fb70ba87 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
index 0ec4c64..ca3d5bf 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
index 60dc8a6..a17e1d7 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
index fe2ba7a..b5ab8b3 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
index 150a6c7..8e9c451 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
index 76f86dc..25e9394 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
index 42a798a..0478d70 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
index 1f0dd89..6de73be 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
index 1643e6e..e78a0b1 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
index 5e7ae35..02d4b3f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
index 06ae2ca..24c75ec 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
index b861bc9..108c054 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
index 8f1831d..7027dc4 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
index 8f16376..a9d22d6 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
index 12138d3..b0e83dc 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
index 67f46d3..0ed3c8f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
index 11fd5e9..01945ff 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
index 165348c..dc36e0e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
index 8bbc5ba..725a507 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
index d53d3bc..f3fd89a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
index c817598..193af25 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
new file mode 100644
index 0000000..22215ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
index ce64926..1fd5dd3 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
index c63c426..b2edd46 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_expand_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
index 85394fa..0eb71d0 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_ticker_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
index 3b7c9c7..90b4baf 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
index 653acbb..bc7034a 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_veto_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
index 6c588f7..6f19bf4 100644
--- a/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/statusbar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
index 13b18d8..9de8324 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_portrait.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
index dbcefee..75a020c 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
index 6e13ebe..4d5135e 100644
--- a/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/bg_scrim_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
old mode 100755
new mode 100644
index 7d17a54..269049e
--- a/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_glow_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
index d960c78..e7828c9 100644
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_bottom.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
old mode 100755
new mode 100644
index 3e46370..0e8c25c
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_left.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
old mode 100755
new mode 100644
index afc91b9..536357a
--- a/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_item_glow_top.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
old mode 100755
new mode 100644
index 7086def..1ea924f
--- a/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
+++ b/packages/SystemUI/res/drawable-nodpi/notify_panel_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
new file mode 100644
index 0000000..275e492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
new file mode 100644
index 0000000..03f4732
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_diagram.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
new file mode 100644
index 0000000..7bfdb46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_bottom.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
new file mode 100644
index 0000000..4e20851
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_divider_top.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
new file mode 100644
index 0000000..1c1b26b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/compat_mode_help_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
new file mode 100644
index 0000000..ed968c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
new file mode 100644
index 0000000..31ac35d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_airplane_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
new file mode 100644
index 0000000..5641b2b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
new file mode 100644
index 0000000..1ea83fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_apps_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4cb305d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
new file mode 100644
index 0000000..85df060
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
new file mode 100644
index 0000000..0019a32
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
new file mode 100644
index 0000000..dc08550
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
new file mode 100644
index 0000000..bc024da
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
new file mode 100644
index 0000000..03885fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_brightness_low.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
new file mode 100644
index 0000000..92e86c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_gps_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
new file mode 100644
index 0000000..2e6e3ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..31d35c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
new file mode 100644
index 0000000..334213b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
new file mode 100644
index 0000000..dd98b0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
new file mode 100644
index 0000000..94acf9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_ime_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
new file mode 100644
index 0000000..155c788
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
new file mode 100644
index 0000000..e84f3fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
new file mode 100644
index 0000000..7c21c48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
new file mode 100644
index 0000000..1fe6b91
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
new file mode 100644
index 0000000..4fc936b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
new file mode 100644
index 0000000..27357ea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_notification_dnd_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
new file mode 100644
index 0000000..bbf5f7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_quicksettings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..f0cc341d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
new file mode 100644
index 0000000..7e8504c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_default_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
new file mode 100644
index 0000000..53c7094
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_lanscape.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
new file mode 100644
index 0000000..a882b94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_off_portrait.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
new file mode 100644
index 0000000..b375396
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_rotate_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
new file mode 100644
index 0000000..fdcf409
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_settings.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
new file mode 100644
index 0000000..792bac4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
new file mode 100644
index 0000000..31b4663
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_off.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
new file mode 100644
index 0000000..45b5bf3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_sound_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
new file mode 100644
index 0000000..54e3d1e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_wifi_on.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..bcea4f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..d915a9d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..6cf2053
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..d4a2068
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..4be3873
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..31e4813
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..032fa29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..52ad541
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d7248b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..5d1a99c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..b342507
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..b618f75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..11946cd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..e227309
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..4b0838c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..ecd4396e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..8c5465a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..9e7992a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..ccf5b0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..04918c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..34da296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f6cb0ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..eb4927a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..14087e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..87b67b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..33fa2ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..a84382f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..b59a72e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c7927d9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..eddb4eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..2759a8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..f129965a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..1abe164
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..06dc700
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..d1ae45d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..0c93241
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..3be20a2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..502382e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..b423454
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b084871
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..8cbaff3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..0e53656
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..55c66b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..103927b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..2a0c21a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..23dfd7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..1258359
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..32c1432
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..b56be83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..cd37477
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
new file mode 100644
index 0000000..347b219
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
new file mode 100644
index 0000000..ef5b653
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
new file mode 100644
index 0000000..cd96a4a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
new file mode 100644
index 0000000..02461a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
new file mode 100644
index 0000000..033267f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
new file mode 100644
index 0000000..73ae175
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
new file mode 100644
index 0000000..1355da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inadnout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
new file mode 100644
index 0000000..ceb316c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
new file mode 100644
index 0000000..ff4a0b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
new file mode 100644
index 0000000..b2ebf40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
new file mode 100644
index 0000000..7f833ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
new file mode 100644
index 0000000..b47e4c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
new file mode 100644
index 0000000..4f88492
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
new file mode 100644
index 0000000..7f7e1ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
new file mode 100644
index 0000000..f0ab081
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
new file mode 100644
index 0000000..e556da1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
new file mode 100644
index 0000000..a28d771
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
new file mode 100644
index 0000000..7be9754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
new file mode 100644
index 0000000..16271a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
new file mode 100644
index 0000000..263c591
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_gps_acquiring.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
new file mode 100644
index 0000000..edff8db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_no_sim.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
new file mode 100644
index 0000000..e7938f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
new file mode 100644
index 0000000..33fda46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
new file mode 100644
index 0000000..1d5484b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
new file mode 100644
index 0000000..478b293
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
new file mode 100644
index 0000000..b9cff0e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
new file mode 100644
index 0000000..4945e23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
new file mode 100644
index 0000000..a55ecd8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
new file mode 100644
index 0000000..0641c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
new file mode 100644
index 0000000..d0eebb6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_r_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
new file mode 100644
index 0000000..cd89105
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_silent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..e85d643
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
new file mode 100644
index 0000000..51b291c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
new file mode 100644
index 0000000..23d30fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
new file mode 100644
index 0000000..51b291c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_roaming_cdma_flash_anim1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..726f7ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..ec4f934
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..a77c8a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
new file mode 100644
index 0000000..fb98eef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..1527803
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
new file mode 100644
index 0000000..b86d47a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
new file mode 100644
index 0000000..e487f5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..64ddafd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
new file mode 100644
index 0000000..7269f96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..6cf7a28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
new file mode 100644
index 0000000..f57e62d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..0bc3d0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
new file mode 100644
index 0000000..3d513fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..34ec231
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
new file mode 100644
index 0000000..32556f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
new file mode 100644
index 0000000..15d0f2f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..c7c1e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
new file mode 100644
index 0000000..afac648
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..6e4dc8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
new file mode 100644
index 0000000..60c0e7f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
new file mode 100644
index 0000000..90ca4e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
new file mode 100644
index 0000000..befa1eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_edge.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..419afa0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
new file mode 100644
index 0000000..93af4fa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_gprs.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
new file mode 100644
index 0000000..c3f9e5d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_hsdpa.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..b20c61b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..b51178d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..0df470a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..485d407
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
new file mode 100644
index 0000000..19cf3b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
new file mode 100644
index 0000000..d28972f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_tty_mode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6ed28c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..4f462ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..66d8f80
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..b2b2ace
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..5212337
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
new file mode 100644
index 0000000..d8d5e8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..43e590b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
new file mode 100644
index 0000000..2b0b54f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..e900d6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
new file mode 100644
index 0000000..85c65b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..990734c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
new file mode 100644
index 0000000..a7e9aaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..d982c1f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
new file mode 100644
index 0000000..21aba7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..daf2750
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
new file mode 100644
index 0000000..41db8dc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..b93e9ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
new file mode 100644
index 0000000..ae95d26
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..576f120
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
new file mode 100644
index 0000000..4ad2c5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
new file mode 100644
index 0000000..52354bd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..ce01276
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..1848fcd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
new file mode 100644
index 0000000..846bc49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..a983e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..7c6e44e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..a08c5f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..6aa38bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..36c26b6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..55940d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..f65ef5b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..8a0f4e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..2d81b22
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..4c08cff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..27d3b50
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..f017dd1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..6cd2c71
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..76195ca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..fb097b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..04740b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..147d256
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..de808a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..d19d6ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..4bce24d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..0467e12
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..0809456
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..0e8ec073
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..f9d2737
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..f5b2c9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..eb1b18a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..1abe28a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..e896cbb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..b44123c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..d0cc5794e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..903b03e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..9578a218
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..c5e5cda
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..0730e3e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..eafed59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..ea66c75
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..4db62e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..69a6ce6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..6f59975
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2b593d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..ef4cac8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..db42b0d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..11ee533
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..43edb8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..7919030
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..0699681
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..9504838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..db8bedb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..89e1b2c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..88f720d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..89fcbd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..0ec439c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..4b22619
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..9b8c889
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..e601a90
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b65c93f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..80fdafe1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..c54f630e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..8cfc59b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..3381016
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..0a77e7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..660b3a0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..0c278ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..921d88b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..4c6c08e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..de32ddd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
new file mode 100644
index 0000000..001811f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/app_icon.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
new file mode 100644
index 0000000..3d0fbf2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
new file mode 100644
index 0000000..4362836
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_blue_glow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
new file mode 100644
index 0000000..f4ccd7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_callout_line.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
new file mode 100644
index 0000000..6392fa1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
new file mode 100644
index 0000000..f6ee596
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..5087adb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4c212e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..bf23074
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..45dcf77
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..a2848de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..89c998b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..9269d6e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..344ae30
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..13b5cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..6647559
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..a0e67c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..9a75c24
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..a1f73c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..6b17f1c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..9553580
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..8507f39
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..6966cec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..84ce77f1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..b8670f2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..a885aab
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..32f08c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..0111893
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..a9c547e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..6801953
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..3ae2537
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..8a9f2e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..8c5c482
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..36c2cf8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..aee1eed
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..30884a96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..ce91aa9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..82a4f61
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..55b6b38
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..519154d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..795c6e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..b7f5346
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..b28bf04
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..2722c21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..596cae5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..50476ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..cdbab37
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..ec398cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..b1f16d6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..e15a12b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..90a1a3d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..21d944a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..9b2263f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..ca36237
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..2cea010
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..3d22838
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3bee795
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..ad6bdce
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..6d68d4e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..04ddb65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..830b006
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..f3be79b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..7f33567
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..471a900
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..b153c83
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..3a5ddb7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..609117c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..d8cd1fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..806b43b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..f699434
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
new file mode 100644
index 0000000..64d8b5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
new file mode 100644
index 0000000..4e718b07
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
new file mode 100644
index 0000000..7306b48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
new file mode 100644
index 0000000..f414632
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
new file mode 100644
index 0000000..9e7a84a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
new file mode 100644
index 0000000..e17ce98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
new file mode 100644
index 0000000..861b0b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
new file mode 100644
index 0000000..fe1330b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
new file mode 100644
index 0000000..d459a00
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
new file mode 100644
index 0000000..debd23e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
new file mode 100644
index 0000000..69ba222
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
new file mode 100644
index 0000000..7d862bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
new file mode 100644
index 0000000..6687c82
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
new file mode 100644
index 0000000..8438e76
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
new file mode 100644
index 0000000..1842da2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
new file mode 100644
index 0000000..f9d2754
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_charge_anim85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
new file mode 100644
index 0000000..892ba42
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_battery_unknown.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..73e0886
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..dc3aae3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
new file mode 100644
index 0000000..9d0fe7e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..d3f6f55
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
new file mode 100644
index 0000000..7170a84
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..febf9588
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..4da4f54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
new file mode 100644
index 0000000..e775572
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
new file mode 100644
index 0000000..5e0617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
new file mode 100644
index 0000000..da2926f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
new file mode 100644
index 0000000..fef89cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_connected_roam.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
new file mode 100644
index 0000000..c543b9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
new file mode 100644
index 0000000..3395fff
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
new file mode 100644
index 0000000..612843d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
new file mode 100644
index 0000000..9de3703
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
new file mode 100644
index 0000000..dabfec5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
new file mode 100644
index 0000000..0ca6fbf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_connected_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_in_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_inandout_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
new file mode 100644
index 0000000..04f8270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_1x.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
new file mode 100644
index 0000000..517705c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
new file mode 100644
index 0000000..947a42c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_4g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
new file mode 100644
index 0000000..5c0ee29
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_e.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
new file mode 100644
index 0000000..31d6c01
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
new file mode 100644
index 0000000..04ae052
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_data_fully_out_h.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
new file mode 100644
index 0000000..aa73096
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
new file mode 100644
index 0000000..b534296
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
new file mode 100644
index 0000000..a33c488
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
new file mode 100644
index 0000000..fdd9c92
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
new file mode 100644
index 0000000..5454b49
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
new file mode 100644
index 0000000..e338fd96
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
new file mode 100644
index 0000000..549b7d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
new file mode 100644
index 0000000..9779320
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..5ca5827
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
new file mode 100644
index 0000000..174ef2d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
new file mode 100644
index 0000000..3e9dece
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
new file mode 100644
index 0000000..8952833
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
new file mode 100644
index 0000000..180a13b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
new file mode 100644
index 0000000..b9efa16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
new file mode 100644
index 0000000..d8493ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
new file mode 100644
index 0000000..885831e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
new file mode 100644
index 0000000..03fcf54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
new file mode 100644
index 0000000..9bf7bec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_1_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
new file mode 100644
index 0000000..15a82ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
new file mode 100644
index 0000000..eb9ce59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_2_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
new file mode 100644
index 0000000..1c62fe3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
new file mode 100644
index 0000000..09cdfc4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_3_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..5447a85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..04187de
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_row.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_row.xml
deleted file mode 100644
index 93085d7..0000000
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_row.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_height"
- >
-
- <ImageButton
- android:id="@+id/veto"
- android:layout_width="48dp"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"
- android:src="@drawable/status_bar_veto"
- android:scaleType="center"
- android:background="@null"
- android:paddingRight="8dp"
- android:paddingLeft="8dp"
- />
-
- <ImageView
- android:id="@+id/large_icon"
- android:layout_width="@android:dimen/notification_large_icon_width"
- android:layout_height="@android:dimen/notification_large_icon_height"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:scaleType="center"
- />
-
- <com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/large_icon"
- android:layout_toLeftOf="@id/veto"
- android:focusable="true"
- android:clickable="true"
- />
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_alignParentBottom="true"
- android:background="@android:drawable/divider_horizontal_dark"
- />
-
-</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index b97c6a5..51e7d97 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -25,106 +25,145 @@
android:layout_width="match_parent"
>
- <FrameLayout
- android:id="@+id/background"
+ <FrameLayout android:id="@+id/rot0"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#FF000000"
>
- <LinearLayout android:id="@+id/rot0"
+ <LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
android:orientation="horizontal"
>
<!-- navigation controls -->
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="wrap_content"
+ <View
+ android:layout_width="40dp"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_back"
+ android:layout_weight="0"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+ android:layout_width="80dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_back_default"
systemui:keyCode="4"
+ android:layout_weight="0"
+ />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:layout_weight="1"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="wrap_content"
+ android:layout_width="80dp"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_home"
+ android:src="@drawable/ic_sysbar_home_default"
systemui:keyCode="3"
+ android:layout_weight="0"
+ />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:layout_weight="1"
/>
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="wrap_content"
+ <ImageView android:id="@+id/recent_apps"
+ android:layout_width="80dp"
android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_menu"
+ android:src="@drawable/ic_sysbar_recent_default"
+ android:layout_weight="0"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+ android:layout_width="40dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_menu_default"
systemui:keyCode="82"
- android:layout_weight="1"
+ android:layout_weight="0"
+ android:visibility="invisible"
/>
</LinearLayout>
- <LinearLayout android:id="@+id/rot90"
- android:layout_height="match_parent"
+ <View android:id="@+id/deadzone"
+ android:layout_height="@dimen/navigation_bar_deadzone_size"
android:layout_width="match_parent"
- android:orientation="vertical"
- android:visibility="gone"
- >
-
- <!-- navigation controls -->
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_menu"
- systemui:keyCode="82"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_home"
- systemui:keyCode="3"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_back"
- systemui:keyCode="4"
- android:layout_weight="1"
- />
- </LinearLayout>
-
- <LinearLayout android:id="@+id/rot270"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="vertical"
- android:visibility="gone"
- >
-
- <!-- navigation controls -->
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_back"
- systemui:keyCode="4"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_home"
- systemui:keyCode="3"
- android:layout_weight="1"
- />
- <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_menu"
- systemui:keyCode="82"
- android:layout_weight="1"
- />
- </LinearLayout>
-
+ android:layout_gravity="top"
+ android:clickable="true"
+ />
</FrameLayout>
+
+ <FrameLayout android:id="@+id/rot90"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="#FF000000"
+ android:visibility="gone"
+ android:paddingTop="24dp"
+ >
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ >
+
+ <!-- navigation controls -->
+ <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+ android:layout_height="40dp"
+ android:layout_width="match_parent"
+ android:src="@drawable/ic_sysbar_menu_default_land"
+ systemui:keyCode="82"
+ android:layout_weight="0"
+ android:visibility="invisible"
+ />
+ <ImageView android:id="@+id/recent_apps"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:src="@drawable/ic_sysbar_recent_default_land"
+ android:layout_weight="0"
+ />
+ <View
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:src="@drawable/ic_sysbar_home_default_land"
+ systemui:keyCode="3"
+ android:layout_weight="0"
+ />
+ <View
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+ android:layout_height="80dp"
+ android:layout_width="match_parent"
+ android:src="@drawable/ic_sysbar_back_default_land"
+ systemui:keyCode="4"
+ android:layout_weight="0"
+ />
+ <View
+ android:layout_height="40dp"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ />
+ </LinearLayout>
+
+ <View android:id="@+id/deadzone"
+ android:layout_width="@dimen/navigation_bar_deadzone_size"
+ android:layout_height="match_parent"
+ android:layout_gravity="left"
+ android:clickable="true"
+ />
+ </FrameLayout>
+
+ <!-- not used -->
+ <View android:id="@+id/rot270"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:visibility="gone"
+ />
+
</com.android.systemui.statusbar.phone.NavigationBarView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 93085d7..aff6a6e 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -9,6 +9,7 @@
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
+ android:layout_marginRight="-80dp"
android:src="@drawable/status_bar_veto"
android:scaleType="center"
android:background="@null"
@@ -30,7 +31,7 @@
android:layout_height="64dp"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/large_icon"
- android:layout_toLeftOf="@id/veto"
+ android:layout_alignParentRight="true"
android:focusable="true"
android:clickable="true"
/>
diff --git a/packages/SystemUI/res/layout/usb_preference_buttons.xml b/packages/SystemUI/res/layout/usb_preference_buttons.xml
new file mode 100644
index 0000000..babe07e
--- /dev/null
+++ b/packages/SystemUI/res/layout/usb_preference_buttons.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Check box that is displayed in the activity resolver UI for the user
+ to make their selection the preferred activity. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="14dip"
+ android:paddingRight="15dip"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/mtp_ptp_button"
+ android:text="@string/use_ptp_button_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:clickable="true" />
+
+ <Button
+ android:id="@+id/installer_cd_button"
+ android:text="@string/installer_cd_button_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:clickable="true" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af-land/strings.xml b/packages/SystemUI/res/values-af-land/strings.xml
new file mode 100644
index 0000000..9db7121
--- /dev/null
+++ b/packages/SystemUI/res/values-af-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Skerm is nou in landskapsoriëntering gesluit."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0c4b41f..c0c39d2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -19,13 +19,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for app_label (7164937344850004466) -->
- <skip />
+ <string name="app_label" msgid="7164937344850004466">"Stelsel-UI"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Maak skoon"</string>
- <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
- <skip />
- <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
- <skip />
+ <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Moenie steur nie"</string>
+ <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Wys kennisgewings"</string>
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -34,35 +31,22 @@
<skip />
<!-- no translation found for battery_low_title (7923774589611311406) -->
<skip />
- <!-- no translation found for battery_low_subtitle (1752040062087829196) -->
- <skip />
- <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
- <skip />
- <!-- no translation found for invalid_charger (4549105996740522523) -->
- <skip />
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Die battery raak pap."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> oor"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB-laaiery nie ondersteun nie."\n"Gebruik net die laaier wat verskaf is."</string>
<string name="battery_low_why" msgid="7279169609518386372">"Batterygebruik"</string>
- <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
- <skip />
- <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
- <skip />
- <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
- <skip />
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Instellings"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Vliegtuigmodus"</string>
<!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
<skip />
- <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
- <skip />
- <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
- <skip />
- <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
- <skip />
- <!-- no translation found for recent_tasks_title (3691764623638127888) -->
- <skip />
- <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
- <skip />
- <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
- <skip />
- <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
- <skip />
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMP"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OUTO"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Kennisgewings"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"Onlangs"</string>
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"Geen onlangse programme nie."</string>
+ <string name="recent_tasks_app_label" msgid="3796483981246752469">"Apps"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-verbind"</string>
<!-- no translation found for status_bar_input_method_settings_configure_input_methods (737483394044014246) -->
<skip />
<!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
@@ -85,4 +69,20 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am-land/strings.xml b/packages/SystemUI/res/values-am-land/strings.xml
new file mode 100644
index 0000000..993b7d3
--- /dev/null
+++ b/packages/SystemUI/res/values-am-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"አሁን ማያበወርድ ገፅ አቀማመጥ ተሸንጉሯል።"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 6d09e83..7b37070 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -19,13 +19,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for app_label (7164937344850004466) -->
- <skip />
+ <string name="app_label" msgid="7164937344850004466">"የስርዓት UI"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
- <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
- <skip />
- <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
- <skip />
+ <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"አይረብሹ"</string>
+ <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"ማሳወቂያዎች አሳይ"</string>
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -34,34 +31,22 @@
<skip />
<!-- no translation found for battery_low_title (7923774589611311406) -->
<skip />
- <!-- no translation found for battery_low_subtitle (1752040062087829196) -->
- <skip />
- <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
- <skip />
- <!-- no translation found for invalid_charger (4549105996740522523) -->
- <skip />
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"ባትሪው እያነሰ ነው።"</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ቀሪ"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB ኃይል መሙያ አይታገዝም።"\n" የቀረበውን ኃይል መሙያ ብቻ ተጠቀም።"</string>
<string name="battery_low_why" msgid="7279169609518386372">"የባትሪ ጥቅም"</string>
- <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
- <skip />
- <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
- <skip />
- <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
- <skip />
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ቅንብሮች"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"የአውሮፕላን ሁነታ"</string>
<!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
<skip />
- <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
- <skip />
- <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
- <skip />
- <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
- <skip />
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ድምጽ አጥፋ"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ራስ ሰር"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"ማሳወቂያዎች"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"የቅርብ ጊዜ"</string>
- <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
- <skip />
- <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
- <skip />
- <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
- <skip />
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"ምንም የቅርብ ጊዜ ትግበራዎች የሉም።"</string>
+ <string name="recent_tasks_app_label" msgid="3796483981246752469">"ትግበራዎች"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"ብሉቱዝ አያይዝ"</string>
<!-- no translation found for status_bar_input_method_settings_configure_input_methods (737483394044014246) -->
<skip />
<!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
@@ -84,4 +69,20 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 399a774..1555048 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"عرض"</string>
<string name="always_use_device" msgid="1450287437017315906">"الاستخدام بشكل افتراضي لجهاز USB هذا"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"الاستخدام بشكل افتراضي لملحق USB هذا"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 0fddf23..1d7f558 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Преглед"</string>
<string name="always_use_device" msgid="1450287437017315906">"Използване по подразб. за това USB устройство"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Използване по подразб. за този аксесоар за USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 64f53d0b..d27cb81 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Mostra"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilitza de manera predet. per al dispositiu USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f1bab7e..e82ad34 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Zobrazit"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pro toto zařízení USB použít jako výchozí"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pro toto periferní zařízení USB použít jako výchozí"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 054b53c..2cdd3cc 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -39,18 +39,34 @@
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
<string name="status_bar_settings_notifications" msgid="397146176280905137">"Meddelelser"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Seneste"</string>
- <string name="recent_tasks_empty" msgid="1905484479067697884">"Der er ingen nye programmer."</string>
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"Der er ingen nye applikationer."</string>
<string name="recent_tasks_app_label" msgid="3796483981246752469">"Programmer"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurer inputmetoder"</string>
<string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string>
- <string name="usb_device_permission_prompt" msgid="3816016361969816903">"Vil du tillade, at programmet <xliff:g id="APPLICATION">%1$s</xliff:g> får adgang til USB-enheden?"</string>
- <string name="usb_accessory_permission_prompt" msgid="6888598803988889959">"Vil du tillade, at programmet <xliff:g id="APPLICATION">%1$s</xliff:g> får adgang til USB-ekstraudstyret?"</string>
+ <string name="usb_device_permission_prompt" msgid="3816016361969816903">"Vil du tillade, at applikationen <xliff:g id="APPLICATION">%1$s</xliff:g> får adgang til USB-enheden?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="6888598803988889959">"Vil du tillade, at applikationen <xliff:g id="APPLICATION">%1$s</xliff:g> får adgang til USB-ekstraudstyret?"</string>
<string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vil du åbne <xliff:g id="ACTIVITY">%1$s</xliff:g>, når denne USB-enhed er tilsluttet?"</string>
<string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Vil du åbne <xliff:g id="ACTIVITY">%1$s</xliff:g>, når dette USB-ekstraudstyr er tilsluttet?"</string>
- <string name="usb_accessory_uri_prompt" msgid="6332150684964235705">"Ingen inst. programmer virker med USB-ekstraudstyret. Få oplysninger om ekstraudstyret på <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="usb_accessory_uri_prompt" msgid="6332150684964235705">"Ingen inst. applikationer virker med USB-ekstraudstyret. Få oplysninger om ekstraudstyret på <xliff:g id="URL">%1$s</xliff:g>"</string>
<string name="title_usb_accessory" msgid="4966265263465181372">"USB-ekstraudstyr"</string>
<string name="label_view" msgid="6304565553218192990">"Vis"</string>
<string name="always_use_device" msgid="1450287437017315906">"Brug som standard til denne USB-enhed"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Brug som standard til dette USB-tilbehør"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 857d3a0..6dc11d1 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Anzeigen"</string>
<string name="always_use_device" msgid="1450287437017315906">"Standardmäßig für dieses USB-Gerät verwenden"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Standardmäßig für dieses USB-Zubehör verwenden"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 424faab..6fd21ce 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Προβολή"</string>
<string name="always_use_device" msgid="1450287437017315906">"Χρήση από προεπιλογή για αυτή τη συσκευή USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Χρήση από προεπιλογή για αυτό το εξάρτημα USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 8c84b67..a7962d2 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -53,4 +53,16 @@
<string name="label_view" msgid="6304565553218192990">"View"</string>
<string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+ <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibility Zoom"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"When an app was designed for a smaller screen, a zoom control will appear by the clock."</string>
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ae747d4..a730459 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Se usa de forma predeterminada para este dispositivo USB."</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Se usa de forma predeterminada para este accesorio USB."</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d58af48..3a489da 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usar de forma predeterminada para este dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usar de forma predeterminada para este accesorio USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b763771..04e5d5f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"مشاهده"</string>
<string name="always_use_device" msgid="1450287437017315906">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"استفاده به صورت پیش فرض برای این دستگاه USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9255dbd..0e20ecb 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Näytä"</string>
<string name="always_use_device" msgid="1450287437017315906">"Käytä oletuksena tällä USB-laitteella"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Käytä oletuksena tällä USB-lisälaitteella"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c41acd3..d765570 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Afficher"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index eda1a93..9eccc49 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
<string name="always_use_device" msgid="1450287437017315906">"Koristi se prema zadanim postavkama za ovaj USB uređaj"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Koristi se prema zadanim postavkama za ovaj USB pribor"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2261c2b..22b9bbb 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Megtekintés"</string>
<string name="always_use_device" msgid="1450287437017315906">"Alapértelmezett használat ehhez az USB-eszközhöz"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Alapértelmezett használat ehhez az USB-kiegészítőhöz"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 53bfc76..14ee7b67 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Lihat"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gunakan secara bawaan untuk perangkat USB ini"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara bawaan untuk aksesori USB ini"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 055e783..b85175f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Visualizza"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usa per impostazione predef. per dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usa per impostazione predef. per accessorio USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 04fa686..8f0a95a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"הצג"</string>
<string name="always_use_device" msgid="1450287437017315906">"השתמש כברירת מחדל עבור התקן USB זה"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"השתמש כברירת מחדל עבור אביזר USB זה"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4ec1d1b..39bf1f1 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"表示"</string>
<string name="always_use_device" msgid="1450287437017315906">"このUSBデバイスにデフォルトで使用する"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"このUSBアクセサリにデフォルトで使用する"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8b80d9d..516bc63 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"보기"</string>
<string name="always_use_device" msgid="1450287437017315906">"이 USB 기기에 기본값으로 사용"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"이 USB 액세서리에 기본값으로 사용"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 4c7986c..3e2733c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Žiūrėti"</string>
<string name="always_use_device" msgid="1450287437017315906">"Šiam USB įreng. naudoti pagal numat. nustatymus"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Šiam USB priedui naudoti pagal numat. nustatymus"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2804ffa..a899170 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Skatīt"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pēc noklusējuma izmantot šai USB ierīcei"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pēc noklusējuma izmantot šim USB piederumam"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms-land/strings.xml b/packages/SystemUI/res/values-ms-land/strings.xml
new file mode 100644
index 0000000..175b0fa
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Skrin kini dikunci dalam orientasi landskap."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index a5150e7..06527d2 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -19,67 +19,54 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for app_label (7164937344850004466) -->
- <skip />
- <!-- no translation found for status_bar_clear_all_button (7774721344716731603) -->
- <skip />
- <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
- <skip />
- <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
- <skip />
+ <string name="app_label" msgid="7164937344850004466">"Sistem UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Pdm bersih"</string>
+ <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Jangan ganggu"</string>
+ <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Tunjukkan pemberitahuan"</string>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tiada pemberitahuan"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sedang berlangsung"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
<string name="battery_low_title" msgid="7923774589611311406">"Sila sambungkan pengecas"</string>
- <!-- outdated translation 7388781709819722764 --> <string name="battery_low_subtitle" msgid="1752040062087829196">"Bateri semakin lemah:"</string>
- <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Bateri semakin lemah."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"Berbaki <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Pengecasan USB tidak disokong."\n"Gunakan hanya pengecas yang dibekalkan."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Penggunaan bateri"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Tetapan"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mod pesawat"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Autoputar skrin"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"REDAM"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string>
+ <string name="recent_tasks_title" msgid="3691764623638127888">"Baru-baru ini"</string>
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"Tiada aplikasi terbaru."</string>
+ <string name="recent_tasks_app_label" msgid="3796483981246752469">"Apl"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ditambatkan"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Konfigurasikan kaedah input"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Guna ppn kekunci fizikal"</string>
+ <string name="usb_device_permission_prompt" msgid="3816016361969816903">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses peranti USB?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="6888598803988889959">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses aksesori USB?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buka <xliff:g id="ACTIVITY">%1$s</xliff:g> apabila peranti USB ini disambungkan?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Buka <xliff:g id="ACTIVITY">%1$s</xliff:g> apabila aksesori USB ini disambungkan?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="6332150684964235705">"Tiada apl yg dipsg boleh berfgsi dgn aksri USB ini. Ketahui ttg aksri ini di <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"Aksesori USB"</string>
+ <string name="label_view" msgid="6304565553218192990">"Lihat"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Gunakan secara lalai untuk peranti USB ini"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Gunakan secara lalai untuk aksesori USB ini"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
<skip />
- <!-- no translation found for invalid_charger (4549105996740522523) -->
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
<skip />
- <!-- no translation found for battery_low_why (7279169609518386372) -->
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
<skip />
- <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
<skip />
- <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
<skip />
- <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
<skip />
- <!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
<skip />
- <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
- <skip />
- <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
- <skip />
- <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
- <skip />
- <!-- no translation found for recent_tasks_title (3691764623638127888) -->
- <skip />
- <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
- <skip />
- <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
- <skip />
- <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
- <skip />
- <!-- no translation found for status_bar_input_method_settings_configure_input_methods (737483394044014246) -->
- <skip />
- <!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
- <skip />
- <!-- no translation found for usb_device_permission_prompt (3816016361969816903) -->
- <skip />
- <!-- no translation found for usb_accessory_permission_prompt (6888598803988889959) -->
- <skip />
- <!-- no translation found for usb_device_confirm_prompt (5161205258635253206) -->
- <skip />
- <!-- no translation found for usb_accessory_confirm_prompt (3808984931830229888) -->
- <skip />
- <!-- no translation found for usb_accessory_uri_prompt (6332150684964235705) -->
- <skip />
- <!-- no translation found for title_usb_accessory (4966265263465181372) -->
- <skip />
- <!-- no translation found for label_view (6304565553218192990) -->
- <skip />
- <!-- no translation found for always_use_device (1450287437017315906) -->
- <skip />
- <!-- no translation found for always_use_accessory (1210954576979621596) -->
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
<skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0dc1040..90dee30 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Vis"</string>
<string name="always_use_device" msgid="1450287437017315906">"Bruk som standard for denne USB-enheten"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Bruk som standard for dette USB-tilbehøret"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 4682f93..92af8fd 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Weergeven"</string>
<string name="always_use_device" msgid="1450287437017315906">"Standaard gebruiken voor dit USB-apparaat"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Standaard gebruiken voor dit USB-accessoire"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 198e3e3..14269df 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Wyświetl"</string>
<string name="always_use_device" msgid="1450287437017315906">"Używaj domyślnie dla tego urządzenia USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Używaj domyślnie dla tego akcesorium USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c79dbf0..eadfa4c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Ver"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilizar por predefinição para este aparelho USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utilizar por predefinição para este acessório USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d37988f..c7d1edf 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Visualizar"</string>
<string name="always_use_device" msgid="1450287437017315906">"Usar por padrão para este dispositivo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Usar por padrão para este acessório USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index b41b9bd..30f317c 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -79,4 +79,20 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index afecb92..c204b82 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Afişaţi"</string>
<string name="always_use_device" msgid="1450287437017315906">"Utilizaţi în mod prestabilit pt. acest dispoz. USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Utiliz. în mod prestabilit pt. acest accesoriu USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 623bb65..b9ac0cb 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Просмотр"</string>
<string name="always_use_device" msgid="1450287437017315906">"Использовать по умолчанию для этого USB-устройства"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Использовать по умолчанию для этого USB-аксессуара"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 0250461..fcb6d14 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Zobraziť"</string>
<string name="always_use_device" msgid="1450287437017315906">"Pre toto zariadenie USB použiť ako predvolené"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Pre toto periférne zar. USB použiť ako predvolené"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index d31a30b..e5e365b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Prikaži"</string>
<string name="always_use_device" msgid="1450287437017315906">"Privzeto uporabi za to napravo USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Privzeto uporabi za ta dodatek USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2c44f67..c6cc7db 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Прикажи"</string>
<string name="always_use_device" msgid="1450287437017315906">"Користи подразумевано за овај USB уређај"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Користи подразумевано за овај USB додатак"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 343d6a8..558f5f8 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Visa"</string>
<string name="always_use_device" msgid="1450287437017315906">"Använd som standard för den här USB-enheten"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Använd som standard för det här USB-tillbehöret"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw-land/strings.xml b/packages/SystemUI/res/values-sw-land/strings.xml
new file mode 100644
index 0000000..c9769c2
--- /dev/null
+++ b/packages/SystemUI/res/values-sw-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bf0b58e..12d86e3 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -19,13 +19,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for app_label (7164937344850004466) -->
- <skip />
+ <string name="app_label" msgid="7164937344850004466">"UI ya Mfumo"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Futa"</string>
- <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
- <skip />
- <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
- <skip />
+ <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Usisumbue"</string>
+ <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Onyesha arifa"</string>
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -34,34 +31,22 @@
<skip />
<!-- no translation found for battery_low_title (7923774589611311406) -->
<skip />
- <!-- no translation found for battery_low_subtitle (1752040062087829196) -->
- <skip />
- <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
- <skip />
- <!-- no translation found for invalid_charger (4549105996740522523) -->
- <skip />
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Betri inaisha."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> zimebakia"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Chaji ya USB haihamiliwi."\n" Tumia chaka iliyopeanwa."</string>
<string name="battery_low_why" msgid="7279169609518386372">"Utumiaji wa betri"</string>
- <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
- <skip />
- <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
- <skip />
- <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
- <skip />
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Mipangilio"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Mtandao-Hewa"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Hali ya Ndege"</string>
<!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
<skip />
- <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
- <skip />
- <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
- <skip />
- <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
- <skip />
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NYAMAZISHA"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"KIOTOMATIKI"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Arifa"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Za hivi karibuni"</string>
- <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
- <skip />
- <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
- <skip />
- <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
- <skip />
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"Hakuna programu za hivi karibuni."</string>
+ <string name="recent_tasks_app_label" msgid="3796483981246752469">"Programu"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth imefungwa"</string>
<!-- no translation found for status_bar_input_method_settings_configure_input_methods (737483394044014246) -->
<skip />
<!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
@@ -84,4 +69,20 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4db4e24..942ce5b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"ดู"</string>
<string name="always_use_device" msgid="1450287437017315906">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์ USB นี้"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"ใช้ค่าเริ่มต้นสำหรับอุปกรณ์เสริม USB นี้"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 8cd8cfa..4178e2ea 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Tingnan"</string>
<string name="always_use_device" msgid="1450287437017315906">"Gamitin bilang default para sa USB device"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Gamitin bilang default sa USB accessory na ito"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 87ffc8b..beeb56f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Görüntüle"</string>
<string name="always_use_device" msgid="1450287437017315906">"Bu USB cihazı için varsayılan olarak kullan"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar için varsayılan olarak kullan"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6ebad57..22529e6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Переглянути"</string>
<string name="always_use_device" msgid="1450287437017315906">"Використовувати за умовчанням для пристрою USB"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Використовувати за умовчанням для аксесуара USB"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 13a5737..41975b8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"Xem"</string>
<string name="always_use_device" msgid="1450287437017315906">"Sử dụng theo mặc định cho thiết bị USB này"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"Sử dụng theo mặc định cho phụ kiện USB này"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 099ed6bf..d87268d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"查看"</string>
<string name="always_use_device" msgid="1450287437017315906">"默认情况下用于该 USB 设备"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"默认情况下用于该 USB 配件"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 1c06dc2..bb14bd6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -53,4 +53,20 @@
<string name="label_view" msgid="6304565553218192990">"查看"</string>
<string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
<string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu-land/strings.xml b/packages/SystemUI/res/values-zu-land/strings.xml
new file mode 100644
index 0000000..9efeef6
--- /dev/null
+++ b/packages/SystemUI/res/values-zu-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"Isikrini okwamanje sivaliwe ekujikelezeni okumile."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 43a87c3..7597c3a4 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -19,13 +19,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- no translation found for app_label (7164937344850004466) -->
- <skip />
+ <string name="app_label" msgid="7164937344850004466">"Uhlelo lwe-UI"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Sula"</string>
- <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
- <skip />
- <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
- <skip />
+ <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ungaphazamisi"</string>
+ <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Bonisa izaziso"</string>
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -34,34 +31,22 @@
<skip />
<!-- no translation found for battery_low_title (7923774589611311406) -->
<skip />
- <!-- no translation found for battery_low_subtitle (1752040062087829196) -->
- <skip />
- <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
- <skip />
- <!-- no translation found for invalid_charger (4549105996740522523) -->
- <skip />
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Ibhetri iya ngokuphela."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"okusele okungu-<xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Ukushaja i-USB akusekelwe."\n"Sebenzisa kuphela ishaja enikeziwe."</string>
<string name="battery_low_why" msgid="7279169609518386372">"Ukusebenzisa ibhetri"</string>
- <!-- no translation found for status_bar_settings_settings_button (3023889916699270224) -->
- <skip />
- <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
- <skip />
- <!-- no translation found for status_bar_settings_airplane (4879879698500955300) -->
- <skip />
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Izilungiselelo"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"I-Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Imodi yendiza"</string>
<!-- no translation found for status_bar_settings_auto_rotation (3790482541357798421) -->
<skip />
- <!-- no translation found for status_bar_settings_mute_label (554682549917429396) -->
- <skip />
- <!-- no translation found for status_bar_settings_auto_brightness_label (511453614962324674) -->
- <skip />
- <!-- no translation found for status_bar_settings_notifications (397146176280905137) -->
- <skip />
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"THULISA"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OKUZENZAKALELAYO"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Izaziso"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Okwakamuva"</string>
- <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
- <skip />
- <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
- <skip />
- <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
- <skip />
+ <string name="recent_tasks_empty" msgid="1905484479067697884">"Azikho izinhlelo zokusebenza zamanje."</string>
+ <string name="recent_tasks_app_label" msgid="3796483981246752469">"Izinhlelo zokusebenza"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Ukusebenzisa i-Bluetooth njengemodemu"</string>
<!-- no translation found for status_bar_input_method_settings_configure_input_methods (737483394044014246) -->
<skip />
<!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) -->
@@ -84,4 +69,20 @@
<skip />
<!-- no translation found for always_use_accessory (1210954576979621596) -->
<skip />
+ <!-- no translation found for compat_mode_on (6623839244840638213) -->
+ <skip />
+ <!-- no translation found for compat_mode_off (4434467572461327898) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_header (7020175705401506719) -->
+ <skip />
+ <!-- no translation found for compat_mode_help_body (4946726776359270040) -->
+ <skip />
+ <!-- no translation found for usb_preference_title (6551050377388882787) -->
+ <skip />
+ <!-- no translation found for use_mtp_button_title (4333504413563023626) -->
+ <skip />
+ <!-- no translation found for use_ptp_button_title (7517127540301625751) -->
+ <skip />
+ <!-- no translation found for installer_cd_button_title (8485631662288445893) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7a4ac5d..5298f2e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -36,10 +36,6 @@
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">true</bool>
- <!-- Whether a software navigation bar should be shown. NOTE: in the future this may be
- autodetected from the Configuration. -->
- <bool name="config_showNavigationBar">false</bool>
-
<!-- How many icons may be shown at once in the system bar. Includes any
slots that may be reused for things like IME control. -->
<integer name="config_maxNotificationIcons">5</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fc35a48..da28e1e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -40,7 +40,11 @@
<dimen name="peek_window_y_offset">-12dp</dimen>
<!-- thickness (height) of the navigation bar on phones that require it -->
- <dimen name="navigation_bar_size">42dp</dimen>
+ <dimen name="navigation_bar_size">48dp</dimen>
+
+ <!-- thickness (height) of the dead zone at the top of the navigation bar,
+ reducing false presses on navbar buttons; approx 2mm -->
+ <dimen name="navigation_bar_deadzone_size">12dp</dimen>
<!-- thickness (height) of each notification row, including any separators or padding -->
<dimen name="notification_height">65dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8945da5..86e0cd0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -156,4 +156,13 @@
<!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] -->
<string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string>
+
+ <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
+ <string name="usb_preference_title">USB file transfer options</string>
+ <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+ <string name="use_mtp_button_title">Mount as a media player (MTP)</string>
+ <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+ <string name="use_ptp_button_title">Mount as a camera (PTP)</string>
+ <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] -->
+ <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index dbfbe11..d9d9c06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -29,6 +29,8 @@
import android.view.ViewDebug;
import android.widget.FrameLayout;
+import java.text.NumberFormat;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.R;
@@ -180,7 +182,18 @@
}
void placeNumber() {
- final String str = mNumberText = Integer.toString(mIcon.number);
+ final String str;
+ final int tooBig = mContext.getResources().getInteger(
+ android.R.integer.status_bar_notification_info_maxnum);
+ if (mIcon.number > tooBig) {
+ str = mContext.getResources().getString(
+ android.R.string.status_bar_notification_info_overflow);
+ } else {
+ NumberFormat f = NumberFormat.getIntegerInstance();
+ str = f.format(mIcon.number);
+ }
+ mNumberText = str;
+
final int w = getWidth();
final int h = getHeight();
final Rect r = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7dafb892..550fc57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -36,14 +36,24 @@
import com.android.systemui.R;
public class NavigationBarView extends LinearLayout {
+ final static boolean DEBUG_DEADZONE = false;
+
final static boolean NAVBAR_ALWAYS_AT_RIGHT = true;
protected IStatusBarService mBarService;
final Display mDisplay;
+ View mCurrentView = null;
View[] mRotatedViews = new View[4];
- View mBackground;
Animator mLastAnimator = null;
+ public View getRecentsButton() {
+ return mCurrentView.findViewById(R.id.recent_apps);
+ }
+
+ public View getMenuButton() {
+ return mCurrentView.findViewById(R.id.menu);
+ }
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
mDisplay = ((WindowManager)context.getSystemService(
@@ -65,13 +75,13 @@
}
private void setLights(final boolean on) {
- float oldAlpha = mBackground.getAlpha();
+ float oldAlpha = mCurrentView.getAlpha();
android.util.Log.d("NavigationBarView", "animating alpha: " + oldAlpha + " -> "
+ (on ? 1f : 0f));
if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
- mLastAnimator = ObjectAnimator.ofFloat(mBackground, "alpha", oldAlpha, on ? 1f : 0f)
+ mLastAnimator = ObjectAnimator.ofFloat(mCurrentView, "alpha", oldAlpha, on ? 1f : 0f)
.setDuration(on ? 250 : 1500);
mLastAnimator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -83,8 +93,6 @@
}
public void onFinishInflate() {
- mBackground = findViewById(R.id.background);
-
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
@@ -93,6 +101,8 @@
mRotatedViews[Surface.ROTATION_270] = NAVBAR_ALWAYS_AT_RIGHT
? findViewById(R.id.rot90)
: findViewById(R.id.rot270);
+
+ mCurrentView = mRotatedViews[Surface.ROTATION_0];
}
@Override
@@ -107,7 +117,12 @@
for (int i=0; i<4; i++) {
mRotatedViews[i].setVisibility(View.GONE);
}
- mRotatedViews[rot].setVisibility(View.VISIBLE);
+ mCurrentView = mRotatedViews[rot];
+ mCurrentView.setVisibility(View.VISIBLE);
+
+ if (DEBUG_DEADZONE) {
+ mCurrentView.findViewById(R.id.deadzone).setBackgroundColor(0x808080FF);
+ }
android.util.Log.d("NavigationBarView", "reorient(): rot=" + mDisplay.getRotation());
}
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 0b82123..4c7b0dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -246,7 +246,7 @@
mIntruderAlertView.setClickable(true);
try {
- boolean showNav = res.getBoolean(R.bool.config_showNavigationBar);
+ boolean showNav = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
if (showNav) {
mNavigationBarView =
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
@@ -372,11 +372,20 @@
return res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
}
+ private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ toggleRecentApps();
+ }
+ };
+
// For small-screen devices (read: phones) that lack hardware navigation buttons
private void addNavigationBar() {
if (mNavigationBarView == null) return;
mNavigationBarView.reorient();
+
+ mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
WindowManagerImpl.getDefault().addView(
mNavigationBarView, getNavigationBarLayoutParams());
}
@@ -385,6 +394,9 @@
if (mNavigationBarView == null) return;
mNavigationBarView.reorient();
+
+ mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
+
WindowManagerImpl.getDefault().updateViewLayout(
mNavigationBarView, getNavigationBarLayoutParams());
}
@@ -1230,8 +1242,20 @@
}
}
+ public void topAppWindowChanged(boolean showMenu) {
+ if (DEBUG) {
+ Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
+ }
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getMenuButton().setVisibility(showMenu
+ ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ // See above re: lights-out policy for legacy apps.
+ if (showMenu) setLightsOn(true);
+ }
+
// Not supported
- public void topAppWindowChanged(boolean visible) { }
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { }
@Override
public void setHardKeyboardStatus(boolean available, boolean enabled) { }
@@ -1721,7 +1745,7 @@
|| Intent.ACTION_SCREEN_OFF.equals(action)) {
boolean excludeRecents = false;
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- String reason = intent.getExtras().getString("reason");
+ String reason = intent.getStringExtra("reason");
if (reason != null) {
excludeRecents = reason.equals("recentapps");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index b5ea7b2..981fb24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -52,11 +52,16 @@
private static final boolean ANIMATE_LAYOUT = true;
+ private static final boolean CLEAR_IF_SWIPED_FAR_ENOUGH = true;
+
+ private static final boolean CONSTRAIN_SWIPE_ON_PERMANENT = true;
+
private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250;
private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN;
private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250;
private static final float SWIPE_ESCAPE_VELOCITY = 1500f;
+ private static final float SWIPE_ANIM_VELOCITY_MIN = 1000f;
Rect mTmpRect = new Rect();
int mNumRows = 0;
@@ -149,6 +154,21 @@
}
return mSlidingChild != null;
}
+
+ protected boolean canBeCleared(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ return (veto != null && veto.getVisibility() != View.GONE);
+ }
+
+ protected boolean clear(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ if (veto != null && veto.getVisibility() != View.GONE) {
+ veto.performClick();
+ return true;
+ }
+ return false;
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
@@ -159,7 +179,13 @@
case MotionEvent.ACTION_MOVE:
mVT.addMovement(ev);
- mSlidingChild.setTranslationX(ev.getX() - mInitialTouchX);
+ float delta = (ev.getX() - mInitialTouchX);
+ if (CONSTRAIN_SWIPE_ON_PERMANENT && !canBeCleared(mSlidingChild)) {
+ delta = Math.copySign(
+ Math.min(Math.abs(delta),
+ mSlidingChild.getMeasuredWidth() * 0.2f), delta);
+ }
+ mSlidingChild.setTranslationX(delta);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
@@ -168,14 +194,13 @@
if (DEBUG) Slog.d(TAG, "exit velocity: " + mVT.getXVelocity());
boolean restore = true;
mLiftoffVelocity = mVT.getXVelocity();
- if (Math.abs(mLiftoffVelocity) > SWIPE_ESCAPE_VELOCITY) {
- // flingadingy
+ if (Math.abs(mLiftoffVelocity) > SWIPE_ESCAPE_VELOCITY
+ || (CLEAR_IF_SWIPED_FAR_ENOUGH &&
+ (mSlidingChild.getTranslationX() * 2) > mSlidingChild.getMeasuredWidth()))
+ {
- View veto = mSlidingChild.findViewById(R.id.veto);
- if (veto != null && veto.getVisibility() == View.VISIBLE) {
- veto.performClick();
- restore = false;
- }
+ // flingadingy
+ restore = ! clear(mSlidingChild);
}
if (restore) {
// snappity
@@ -230,7 +255,8 @@
child.setPivotY(0);
final float velocity = (mSlidingChild == child)
- ? mLiftoffVelocity : SWIPE_ESCAPE_VELOCITY;
+ ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN)
+ : SWIPE_ESCAPE_VELOCITY;
final TimeAnimator zoom = new TimeAnimator();
zoom.setTimeListener(new TimeAnimator.TimeListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 93f7af3..df09f84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1001,14 +1001,14 @@
mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
}
- public void topAppWindowChanged(boolean windowVisible) {
+ public void topAppWindowChanged(boolean showMenu) {
if (DEBUG) {
- Slog.d(TAG, (windowVisible?"showing":"hiding") + " the MENU button");
+ Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
}
- mMenuButton.setVisibility(windowVisible ? View.VISIBLE : View.GONE);
+ mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
// See above re: lights-out policy for legacy apps.
- if (windowVisible) setLightsOn(true);
+ if (showMenu) setLightsOn(true);
mCompatModeButton.refresh();
if (mCompatModeButton.getVisibility() == View.VISIBLE) {
@@ -1040,7 +1040,7 @@
}
});
- WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
new file mode 100644
index 0000000..60906a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java
@@ -0,0 +1,96 @@
+/*
+ * 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.systemui.usb;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.util.Log;
+import android.widget.Button;
+
+import java.io.File;
+
+import com.android.systemui.R;
+
+public class UsbPreferenceActivity extends Activity implements View.OnClickListener {
+
+ private static final String TAG = "UsbPreferenceActivity";
+
+ private UsbManager mUsbManager;
+ private String mCurrentFunction;
+ private String[] mFunctions;
+ private String mInstallerImagePath;
+ private AlertDialog mDialog;
+ private Button mMtpPtpButton;
+ private Button mInstallerCdButton;
+ private boolean mPtpActive;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
+
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+ dialogBuilder.setTitle(getString(R.string.usb_preference_title));
+
+ LayoutInflater inflater = (LayoutInflater)getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null);
+ dialogBuilder.setView(buttonView);
+ mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button);
+ mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button);
+ mMtpPtpButton.setOnClickListener(this);
+ mInstallerCdButton.setOnClickListener(this);
+
+ mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP);
+ if (mPtpActive) {
+ mMtpPtpButton.setText(R.string.use_mtp_button_title);
+ }
+
+ mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath);
+ if (!(new File(mInstallerImagePath)).exists()) {
+ mInstallerCdButton.setVisibility(View.GONE);
+ }
+
+ mDialog = dialogBuilder.show();
+ }
+
+ public void onClick(View v) {
+ if (v.equals(mMtpPtpButton)) {
+ if (mPtpActive) {
+ mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
+ } else {
+ mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true);
+ }
+ } else if (v.equals(mInstallerCdButton)) {
+ // installer CD is never default
+ mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, false);
+ mUsbManager.setMassStorageBackingFile(mInstallerImagePath);
+ }
+
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ finish();
+ }
+}
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index f1da49d..ba3f344 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -35,16 +35,16 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.net.VpnConfig;
+
import java.io.DataInputStream;
import java.io.FileInputStream;
-public class ManageDialog extends Activity implements
+public class ManageDialog extends Activity implements Handler.Callback,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
private static final String TAG = "VpnManage";
- private String mPackageName;
- private String mInterfaceName;
- private long mStartTime;
+ private VpnConfig mConfig;
private IConnectivityManager mService;
@@ -53,28 +53,23 @@
private TextView mDataTransmitted;
private TextView mDataReceived;
- private Updater mUpdater;
+ private Handler mHandler;
@Override
protected void onResume() {
super.onResume();
try {
- Intent intent = getIntent();
- // TODO: Move constants into VpnBuilder.
- mPackageName = intent.getStringExtra("packageName");
- mInterfaceName = intent.getStringExtra("interfaceName");
- mStartTime = intent.getLongExtra("startTime", 0);
+ mConfig = getIntent().getParcelableExtra("config");
mService = IConnectivityManager.Stub.asInterface(
ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
PackageManager pm = getPackageManager();
- ApplicationInfo app = pm.getApplicationInfo(mPackageName, 0);
+ ApplicationInfo app = pm.getApplicationInfo(mConfig.packageName, 0);
View view = View.inflate(this, R.layout.manage, null);
- String session = intent.getStringExtra("session");
- if (session != null) {
- ((TextView) view.findViewById(R.id.session)).setText(session);
+ if (mConfig.sessionName != null) {
+ ((TextView) view.findViewById(R.id.session)).setText(mConfig.sessionName);
}
mDuration = (TextView) view.findViewById(R.id.duration);
mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
@@ -84,15 +79,21 @@
.setIcon(app.loadIcon(pm))
.setTitle(app.loadLabel(pm))
.setView(view)
- .setPositiveButton(R.string.configure, this)
.setNeutralButton(R.string.disconnect, this)
.setNegativeButton(android.R.string.cancel, this)
.create();
+
+ if (mConfig.configureActivity != null) {
+ mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
+ getText(R.string.configure), this);
+ }
mDialog.setOnDismissListener(this);
mDialog.show();
- mUpdater = new Updater();
- mUpdater.sendEmptyMessage(0);
+ if (mHandler == null) {
+ mHandler = new Handler(this);
+ }
+ mHandler.sendEmptyMessage(0);
} catch (Exception e) {
Log.e(TAG, "onResume", e);
finish();
@@ -112,14 +113,15 @@
public void onClick(DialogInterface dialog, int which) {
try {
if (which == AlertDialog.BUTTON_POSITIVE) {
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setPackage(mPackageName);
+ Intent intent = new Intent();
+ intent.setClassName(mConfig.packageName, mConfig.configureActivity);
startActivity(intent);
} else if (which == AlertDialog.BUTTON_NEUTRAL) {
- mService.prepareVpn(mPackageName);
+ mService.prepareVpn("");
}
} catch (Exception e) {
Log.e(TAG, "onClick", e);
+ finish();
}
}
@@ -128,30 +130,30 @@
finish();
}
- private class Updater extends Handler {
- public void handleMessage(Message message) {
- removeMessages(0);
+ @Override
+ public boolean handleMessage(Message message) {
+ mHandler.removeMessages(0);
- if (mDialog.isShowing()) {
- if (mStartTime != 0) {
- long seconds = (SystemClock.elapsedRealtime() - mStartTime) / 1000;
- mDuration.setText(String.format("%02d:%02d:%02d",
- seconds / 3600, seconds / 60 % 60, seconds % 60));
- }
-
- String[] numbers = getStatistics();
- if (numbers != null) {
- // [1] and [2] are received data in bytes and packets.
- mDataReceived.setText(getString(R.string.data_value_format,
- numbers[1], numbers[2]));
-
- // [9] and [10] are transmitted data in bytes and packets.
- mDataTransmitted.setText(getString(R.string.data_value_format,
- numbers[9], numbers[10]));
- }
- sendEmptyMessageDelayed(0, 1000);
+ if (mDialog.isShowing()) {
+ if (mConfig.startTime != 0) {
+ long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000;
+ mDuration.setText(String.format("%02d:%02d:%02d",
+ seconds / 3600, seconds / 60 % 60, seconds % 60));
}
+
+ String[] numbers = getStatistics();
+ if (numbers != null) {
+ // [1] and [2] are received data in bytes and packets.
+ mDataReceived.setText(getString(R.string.data_value_format,
+ numbers[1], numbers[2]));
+
+ // [9] and [10] are transmitted data in bytes and packets.
+ mDataTransmitted.setText(getString(R.string.data_value_format,
+ numbers[9], numbers[10]));
+ }
+ mHandler.sendEmptyMessageDelayed(0, 1000);
}
+ return true;
}
private String[] getStatistics() {
@@ -159,7 +161,7 @@
try {
// See dev_seq_printf_stats() in net/core/dev.c.
in = new DataInputStream(new FileInputStream("/proc/net/dev"));
- String prefix = mInterfaceName + ':';
+ String prefix = mConfig.interfaceName + ':';
while (true) {
String line = in.readLine().trim();
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
index c4feefd..de4ea75 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -110,7 +110,7 @@
mOk = (Button) findViewById(R.id.ok);
mOk.setOnClickListener(this);
- mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
+ mEmergencyCall = (Button) findViewById(R.id.emergencyCallButton);
mEmergencyCall.setOnClickListener(this);
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index eea30407..b60bae7 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -682,8 +682,9 @@
final boolean usingLockPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
- boolean showSlidingTab = getResources().getBoolean(R.bool.config_enableSlidingTabFirst);
- if (isSecure() && (usingLockPattern || !showSlidingTab)) {
+ boolean showLockBeforeUnlock = getResources()
+ .getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
+ if (isSecure() && (usingLockPattern || !showLockBeforeUnlock)) {
return Mode.UnlockScreen;
} else {
return Mode.LockScreen;
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 8b7a61e..1c4084c 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -64,7 +64,6 @@
private KeyguardUpdateMonitor mUpdateMonitor;
private KeyguardScreenCallback mCallback;
- private SlidingTab mSlidingTab;
private TextView mScreenLocked;
private TextView mEmergencyCallText;
private Button mEmergencyCallButton;
@@ -89,11 +88,9 @@
private boolean mEnableMenuKeyInLockScreen;
private StatusView mStatusView;
- private WaveView mEnergyWave;
- private SlidingTabMethods mSlidingTabMethods;
- private WaveViewMethods mWaveViewMethods;
- private MultiWaveView mMultiWaveView;
- private MultiWaveViewMethods mMultiWaveViewMethods;
+ private UnlockWidgetCommonMethods mUnlockWidgetMethods;
+ private View mUnlockWidget;
+
/**
* The status of this lock screen.
@@ -151,9 +148,28 @@
}
}
- class SlidingTabMethods implements SlidingTab.OnTriggerListener {
+ private interface UnlockWidgetCommonMethods {
+ // Update resources based on phone state
+ public void updateResources();
- private void updateRightTabResources() {
+ // Get the view associated with this widget
+ public View getView();
+
+ // Reset the view
+ public void reset(boolean animate);
+
+ // Animate the widget if it supports ping()
+ public void ping();
+ }
+
+ class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
+ private final SlidingTab mSlidingTab;
+
+ SlidingTabMethods(SlidingTab slidingTab) {
+ mSlidingTab = slidingTab;
+ }
+
+ public void updateResources() {
boolean vibe = mSilentMode
&& (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
@@ -175,7 +191,6 @@
mCallback.goToUnlockScreen();
} else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
toggleRingMode();
- updateRightTabResources();
doSilenceRingToast();
mCallback.pokeWakelock();
}
@@ -195,12 +210,29 @@
mCallback.pokeWakelock();
}
}
+
+ public View getView() {
+ return mSlidingTab;
+ }
+
+ public void reset(boolean animate) {
+ mSlidingTab.reset(animate);
+ }
+
+ public void ping() {
+ }
}
private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
- class WaveViewMethods implements WaveView.OnTriggerListener {
+ class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
+
+ private final WaveView mWaveView;
+
+ WaveViewMethods(WaveView waveView) {
+ mWaveView = waveView;
+ }
/** {@inheritDoc} */
public void onTrigger(View v, int whichHandle) {
if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
@@ -210,8 +242,6 @@
/** {@inheritDoc} */
public void onGrabbedStateChange(View v, int grabbedState) {
- if (DBG) Log.v(TAG, "*** LockScreen accel is "
- + (mEnergyWave.isHardwareAccelerated() ? "on":"off"));
// Don't poke the wake lock when returning to a state where the handle is
// not grabbed since that can happen when the system (instead of the user)
// cancels the grab.
@@ -219,30 +249,51 @@
mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
}
}
+
+ public void updateResources() {
+ }
+
+ public View getView() {
+ return mWaveView;
+ }
+ public void reset(boolean animate) {
+ mWaveView.reset();
+ }
+ public void ping() {
+ }
}
- class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener {
+ class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
+ UnlockWidgetCommonMethods {
+
+ private final MultiWaveView mMultiWaveView;
+
+ MultiWaveViewMethods(MultiWaveView multiWaveView) {
+ mMultiWaveView = multiWaveView;
+ }
+
+ public void updateResources() {
+ mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
+ : R.array.lockscreen_targets_when_soundon);
+ }
+
public void onGrabbed(View v, int handle) {
}
+
public void onReleased(View v, int handle) {
}
+
public void onTrigger(View v, int target) {
if (target == 0) { // TODO: Use resources to determine which handle was used
mCallback.goToUnlockScreen();
} else if (target == 2) {
toggleRingMode();
- updateResources();
doSilenceRingToast();
+ mUnlockWidgetMethods.updateResources();
mCallback.pokeWakelock();
}
-
- }
-
- private void updateResources() {
- mMultiWaveView.setTargetResources(mSilentMode ? R.array.lockscreen_targets_when_silent
- : R.array.lockscreen_targets_when_soundon);
}
public void onGrabbedStateChange(View v, int handle) {
@@ -253,6 +304,18 @@
mCallback.pokeWakelock();
}
}
+
+ public View getView() {
+ return mMultiWaveView;
+ }
+
+ public void reset(boolean animate) {
+ mMultiWaveView.reset(animate);
+ }
+
+ public void ping() {
+ mMultiWaveView.ping();
+ }
}
private void requestUnlockScreen() {
@@ -371,32 +434,39 @@
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mSilentMode = isSilentMode();
- View unlockWidget = findViewById(R.id.unlock_widget);
- if (unlockWidget instanceof SlidingTab) {
- mSlidingTab = (SlidingTab) unlockWidget;
- mSlidingTab.setHoldAfterTrigger(true, false);
- mSlidingTab.setLeftHintText(R.string.lockscreen_unlock_label);
- mSlidingTab.setLeftTabResources(
+ mUnlockWidget = findViewById(R.id.unlock_widget);
+ if (mUnlockWidget instanceof SlidingTab) {
+ SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
+ slidingTabView.setHoldAfterTrigger(true, false);
+ slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
+ slidingTabView.setLeftTabResources(
R.drawable.ic_jog_dial_unlock,
R.drawable.jog_tab_target_green,
R.drawable.jog_tab_bar_left_unlock,
R.drawable.jog_tab_left_unlock);
- mSlidingTabMethods = new SlidingTabMethods();
- mSlidingTab.setOnTriggerListener(mSlidingTabMethods);
- mSlidingTabMethods.updateRightTabResources();
- } else if (unlockWidget instanceof WaveView) {
- mEnergyWave = (WaveView) unlockWidget;
- mWaveViewMethods = new WaveViewMethods();
- mEnergyWave.setOnTriggerListener(mWaveViewMethods);
- } else if (unlockWidget instanceof MultiWaveView) {
- mMultiWaveView = (MultiWaveView) unlockWidget;
- mMultiWaveViewMethods = new MultiWaveViewMethods();
- mMultiWaveViewMethods.updateResources(); // update silence/ring resources
- mMultiWaveView.setOnTriggerListener(mMultiWaveViewMethods);
+ SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
+ slidingTabView.setOnTriggerListener(slidingTabMethods);
+ mUnlockWidgetMethods = slidingTabMethods;
+ } else if (mUnlockWidget instanceof WaveView) {
+ WaveView waveView = (WaveView) mUnlockWidget;
+ WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
+ waveView.setOnTriggerListener(waveViewMethods);
+ mUnlockWidgetMethods = waveViewMethods;
+ } else if (mUnlockWidget instanceof MultiWaveView) {
+ MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
+ MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
+ multiWaveView.setOnTriggerListener(multiWaveViewMethods);
+ mUnlockWidgetMethods = multiWaveViewMethods;
} else {
- throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
+ throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
}
+ // Update widget with initial ring state
+ mUnlockWidgetMethods.updateResources();
+
+ if (DBG) Log.v(TAG, "*** LockScreen accel is "
+ + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
+
resetStatusInfo(updateMonitor);
}
@@ -540,16 +610,14 @@
* Enables unlocking of this screen. Typically just shows the unlock widget.
*/
private void enableUnlock() {
- if (mEnergyWave != null) mEnergyWave.setVisibility(View.VISIBLE);
- if (mSlidingTab != null) mSlidingTab.setVisibility(View.VISIBLE);
+ mUnlockWidgetMethods.getView().setVisibility(View.VISIBLE);
}
/**
* Disable unlocking of this screen. Typically just hides the unlock widget.
*/
private void disableUnlock() {
- if (mEnergyWave != null) mEnergyWave.setVisibility(View.GONE);
- if (mSlidingTab != null) mSlidingTab.setVisibility(View.GONE);
+ mUnlockWidgetMethods.getView().setVisibility(View.GONE);
}
/**
@@ -728,20 +796,13 @@
/** {@inheritDoc} */
public void onPause() {
- if (mEnergyWave != null) {
- mEnergyWave.reset();
- }
- if (mMultiWaveView != null) {
- mMultiWaveView.reset(false);
- }
+ mUnlockWidgetMethods.reset(false);
}
/** {@inheritDoc} */
public void onResume() {
resetStatusInfo(mUpdateMonitor);
- if (mMultiWaveView != null) {
- mMultiWaveView.ping();
- }
+ mUnlockWidgetMethods.ping();
}
/** {@inheritDoc} */
@@ -757,7 +818,7 @@
boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
if (silent != mSilentMode) {
mSilentMode = silent;
- if (mSlidingTabMethods != null) mSlidingTabMethods.updateRightTabResources();
+ mUnlockWidgetMethods.updateResources();
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 6734005..f862d01 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -129,7 +129,7 @@
| InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mEmergencyCallButton.setOnClickListener(this);
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index a685497..6573286 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -23,6 +23,7 @@
import android.security.KeyStore;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.MotionEvent;
import android.widget.Button;
@@ -73,12 +74,8 @@
private boolean mEnableFallback;
private StatusView mStatusView;
-
private LockPatternView mLockPatternView;
- private ViewGroup mFooterNormal;
- private ViewGroup mFooterForgotPattern;
-
/**
* Keeps track of the last time we poked the wake lock during dispatching
* of the touch event, initalized to something gauranteed to make us
@@ -96,9 +93,20 @@
}
};
+ private final OnClickListener mEmergencyClick = new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.takeEmergencyCallAction();
+ }
+ };
+
+ private final OnClickListener mForgotPatternClick = new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.forgotPattern(true);
+ }
+ };
+
private Button mForgotPatternButton;
- private Button mEmergencyAlone;
- private Button mEmergencyTogether;
+ private Button mEmergencyButton;
private int mCreationOrientation;
enum FooterMode {
@@ -107,23 +115,27 @@
VerifyUnlocked
}
+ private void hideForgotPatternButton() {
+ mForgotPatternButton.setVisibility(View.GONE);
+ }
+
+ private void showForgotPatternButton() {
+ mForgotPatternButton.setVisibility(View.VISIBLE);
+ }
+
private void updateFooter(FooterMode mode) {
switch (mode) {
case Normal:
- Log.d(TAG, "mode normal");
- mFooterNormal.setVisibility(View.VISIBLE);
- mFooterForgotPattern.setVisibility(View.GONE);
+ if (DEBUG) Log.d(TAG, "mode normal");
+ hideForgotPatternButton();
break;
case ForgotLockPattern:
- Log.d(TAG, "mode ForgotLockPattern");
- mFooterNormal.setVisibility(View.GONE);
- mFooterForgotPattern.setVisibility(View.VISIBLE);
- mForgotPatternButton.setVisibility(View.VISIBLE);
+ if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
+ showForgotPatternButton();
break;
case VerifyUnlocked:
- Log.d(TAG, "mode VerifyUnlocked");
- mFooterNormal.setVisibility(View.GONE);
- mFooterForgotPattern.setVisibility(View.GONE);
+ if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
+ hideForgotPatternButton();
}
}
@@ -171,37 +183,20 @@
mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
// This shows up when no other information is required on status1
- mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,
- StatusView.LOCK_ICON);
+ //mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,StatusView.LOCK_ICON);
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
- mFooterNormal = (ViewGroup) findViewById(R.id.footerNormal);
- mFooterForgotPattern = (ViewGroup) findViewById(R.id.footerForgotPattern);
-
// emergency call buttons
- final OnClickListener emergencyClick = new OnClickListener() {
- public void onClick(View v) {
- mCallback.takeEmergencyCallAction();
- }
- };
+ mEmergencyButton = (Button) findViewById(R.id.emergencyCallButton);
+ mEmergencyButton.setFocusable(false); // touch only!
+ mEmergencyButton.setOnClickListener(mEmergencyClick);
- mEmergencyAlone = (Button) findViewById(R.id.emergencyCallAlone);
- mEmergencyAlone.setFocusable(false); // touch only!
- mEmergencyAlone.setOnClickListener(emergencyClick);
- mEmergencyTogether = (Button) findViewById(R.id.emergencyCallTogether);
- mEmergencyTogether.setFocusable(false);
- mEmergencyTogether.setOnClickListener(emergencyClick);
refreshEmergencyButtonText();
- mForgotPatternButton = (Button) findViewById(R.id.forgotPattern);
+ mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton);
mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
- mForgotPatternButton.setOnClickListener(new OnClickListener() {
-
- public void onClick(View v) {
- mCallback.forgotPattern(true);
- }
- });
+ mForgotPatternButton.setOnClickListener(mForgotPatternClick);
// make it so unhandled touch events within the unlock screen go to the
// lock pattern view.
@@ -232,8 +227,7 @@
}
private void refreshEmergencyButtonText() {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyAlone);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyTogether);
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyButton);
}
public void setEnableFallback(boolean state) {
@@ -338,8 +332,11 @@
mLockPatternView.clearPattern();
// show "forgot pattern?" button if we have an alternate authentication method
- mForgotPatternButton.setVisibility(mCallback.doesFallbackUnlockScreenExist()
- ? View.VISIBLE : View.INVISIBLE);
+ if (mCallback.doesFallbackUnlockScreenExist()) {
+ showForgotPatternButton();
+ } else {
+ hideForgotPatternButton();
+ }
// if the user is currently locked out, enforce it.
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 75f466a..7f6327d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -498,6 +498,7 @@
return;
}
+ int width = WRAP_CONTENT;
if (st.decorView == null || st.refreshDecorView) {
if (st.decorView == null) {
// Initialize the panel decor, this will populate st.decorView
@@ -523,6 +524,7 @@
// If the contents is fill parent for the width, set the
// corresponding background
backgroundResId = st.fullBackground;
+ width = MATCH_PARENT;
} else {
// Otherwise, set the normal panel background
backgroundResId = st.background;
@@ -546,7 +548,7 @@
st.isHandled = false;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- WRAP_CONTENT, WRAP_CONTENT,
+ width, WRAP_CONTENT,
st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
WindowManager.LayoutParams.FLAG_DITHER
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
@@ -709,9 +711,7 @@
mActionBar.isOverflowReserved()) {
if (mActionBar.getVisibility() == View.VISIBLE) {
if (!mActionBar.isOverflowMenuShowing()) {
- final Callback cb = getCallback();
- if (cb != null && !isDestroyed() &&
- cb.onPreparePanel(featureId, st.createdPanelView, st.menu)) {
+ if (!isDestroyed() && preparePanel(st, event)) {
playSoundEffect = mActionBar.showOverflowMenu();
}
} else {
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 544bb3d..7e8d547 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -109,7 +109,7 @@
mDelPinButton.setOnClickListener(this);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mOkButton = (TextView) findViewById(R.id.ok);
mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index 7255c27..ec917f0 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -99,7 +99,7 @@
mOkButton.setOnClickListener(this);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mEmergencyCallButton.setOnClickListener(this);
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 46ce5a3..79f81ff 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -40,7 +40,7 @@
private String mInstructions = null;
private TextView mStatus1;
- private TextView mPropertyOf;
+ private TextView mOwnerInfo;
private boolean mHasCarrier;
private boolean mHasDate;
@@ -105,7 +105,7 @@
mStatus1 = (TextView) findViewById(R.id.status1);
mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
mAlarmStatus.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
- mPropertyOf = (TextView) findViewById(R.id.propertyOf);
+ mOwnerInfo = (TextView) findViewById(R.id.propertyOf);
resetStatusInfo(updateMonitor, lockPatternUtils);
@@ -153,20 +153,22 @@
void updateStatusLines(boolean showStatusLines) {
if (!showStatusLines) {
mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
- mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
+ mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
return;
}
// Update owner info
- if (mPropertyOf != null) {
- ContentResolver res = getContext().getContentResolver();
- String info = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
- boolean enabled = Settings.Secure.getInt(res,
- Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
-
- mPropertyOf.setText(info);
- mPropertyOf.setVisibility(enabled && !TextUtils.isEmpty(info) ?
- View.VISIBLE : View.INVISIBLE);
+ final ContentResolver res = getContext().getContentResolver();
+ final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
+ Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+ String ownerInfo = null;
+ if (ownerInfoEnabled) {
+ ownerInfo = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
+ if (mOwnerInfo != null) {
+ mOwnerInfo.setText(ownerInfo);
+ mOwnerInfo.setVisibility(ownerInfoEnabled && !TextUtils.isEmpty(ownerInfo) ?
+ View.VISIBLE : View.INVISIBLE);
+ }
}
// Update Alarm status
@@ -175,7 +177,7 @@
mAlarmStatus.setText(nextAlarm);
mAlarmStatus.setVisibility(View.VISIBLE);
} else {
- mAlarmStatus.setVisibility(View.INVISIBLE);
+ mAlarmStatus.setVisibility(View.GONE);
}
// Update Status1
@@ -204,15 +206,16 @@
} else {
mStatus1.setVisibility(View.INVISIBLE);
}
+ } else if (mHelpMessageId != 0) {
+ mStatus1.setText(mHelpMessageId);
+ mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
+ mStatus1.setVisibility(View.VISIBLE);
+ } else if (ownerInfoEnabled && mOwnerInfo == null && ownerInfo != null) {
+ mStatus1.setText(ownerInfo);
+ mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0,0, 0);
+ mStatus1.setVisibility(View.VISIBLE);
} else {
- // nothing specific to show; show help message and icon, if provided
- if (mHelpMessageId != 0) {
- mStatus1.setText(mHelpMessageId);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
- mStatus1.setVisibility(View.VISIBLE);
- } else {
- mStatus1.setVisibility(View.INVISIBLE);
- }
+ mStatus1.setVisibility(View.INVISIBLE);
}
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 44df5b5..f716e63 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2936,7 +2936,7 @@
mStreamType = streamType;
// NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
// 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
- mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(int8_t);
+ mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * audio_bytes_per_sample(format) : sizeof(uint8_t);
}
}
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a3749cf..a583aad 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -559,13 +559,8 @@
ANativeWindowBuffer* anb;
rc = a->dequeueBuffer(a, &anb);
if (!rc) {
- rc = a->lockBuffer(a, anb);
- if (!rc) {
- *buffer = &anb->handle;
- *stride = anb->stride;
- }
- else
- a->cancelBuffer(a, anb);
+ *buffer = &anb->handle;
+ *stride = anb->stride;
}
return rc;
}
@@ -576,6 +571,14 @@
(type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
#endif
+ static int __lock_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->lockBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
static int __enqueue_buffer(struct preview_stream_ops* w,
buffer_handle_t* buffer)
{
@@ -641,6 +644,7 @@
void initHalPreviewWindow()
{
mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+ mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a011ae2..9b09983 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -420,6 +420,10 @@
// allow anyone to use camera (after they lock the camera)
status_t result = checkPid();
if (result == NO_ERROR) {
+ if (mHardware->recordingEnabled()) {
+ LOGE("Not allowed to unlock camera during recording.");
+ return INVALID_OPERATION;
+ }
mClientPid = 0;
LOG1("clear mCameraClient (pid %d)", callingPid);
// we need to remove the reference to ICameraClient so that when the app
@@ -756,6 +760,11 @@
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
+ if (mHardware->recordingEnabled()) {
+ LOGE("Cannot take picture during recording.");
+ return INVALID_OPERATION;
+ }
+
if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
(msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
LOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 4a50d8a..85ce38a 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -569,9 +569,9 @@
break;
case DROP_REASON_BLOCKED:
LOGI("Dropped event because the current application is not responding and the user "
- "has started interating with a different application.");
+ "has started interacting with a different application.");
reason = "inbound event was dropped because the current application is not responding "
- "and the user has started interating with a different application";
+ "and the user has started interacting with a different application";
break;
case DROP_REASON_STALE:
LOGI("Dropped event because it is stale.");
@@ -1239,37 +1239,35 @@
const InputWindow* newHoverWindow = NULL;
bool isSplit = mTouchState.split;
- bool wrongDevice = mTouchState.down
- && (mTouchState.deviceId != entry->deviceId
- || mTouchState.source != entry->source);
+ bool switchedDevice = mTouchState.deviceId != entry->deviceId
+ || mTouchState.source != entry->source;
bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
|| maskedAction == AMOTION_EVENT_ACTION_SCROLL
|| isHoverAction);
+ bool wrongDevice = false;
if (newGesture) {
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- if (wrongDevice && !down) {
+ if (switchedDevice && mTouchState.down && !down) {
+#if DEBUG_FOCUS
+ LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
mTempTouchState.copyFrom(mTouchState);
- } else {
- mTempTouchState.reset();
- mTempTouchState.down = down;
- mTempTouchState.deviceId = entry->deviceId;
- mTempTouchState.source = entry->source;
- isSplit = false;
- wrongDevice = false;
+ injectionResult = INPUT_EVENT_INJECTION_FAILED;
+ switchedDevice = false;
+ wrongDevice = true;
+ goto Failed;
}
+ mTempTouchState.reset();
+ mTempTouchState.down = down;
+ mTempTouchState.deviceId = entry->deviceId;
+ mTempTouchState.source = entry->source;
+ isSplit = false;
} else {
mTempTouchState.copyFrom(mTouchState);
}
- if (wrongDevice) {
-#if DEBUG_FOCUS
- LOGD("Dropping event because a pointer for a different device is already down.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
/* Case 1: New splittable pointer going down, or need target for hover or scroll. */
@@ -1598,18 +1596,38 @@
// Update final pieces of touch state if the injector had permission.
if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
if (!wrongDevice) {
- if (maskedAction == AMOTION_EVENT_ACTION_UP
- || maskedAction == AMOTION_EVENT_ACTION_CANCEL
- || isHoverAction) {
+ if (switchedDevice) {
+#if DEBUG_FOCUS
+ LOGD("Conflicting pointer actions: Switched to a different device.");
+#endif
+ *outConflictingPointerActions = true;
+ }
+
+ if (isHoverAction) {
+ // Started hovering, therefore no longer down.
+ if (mTouchState.down) {
+#if DEBUG_FOCUS
+ LOGD("Conflicting pointer actions: Hover received while pointer was down.");
+#endif
+ *outConflictingPointerActions = true;
+ }
+ mTouchState.reset();
+ if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
+ || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+ mTouchState.deviceId = entry->deviceId;
+ mTouchState.source = entry->source;
+ }
+ } else if (maskedAction == AMOTION_EVENT_ACTION_UP
+ || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
// All pointers up or canceled.
mTouchState.reset();
} else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
// First pointer went down.
if (mTouchState.down) {
- *outConflictingPointerActions = true;
#if DEBUG_FOCUS
- LOGD("Pointer down received while already down.");
+ LOGD("Conflicting pointer actions: Down received while already down.");
#endif
+ *outConflictingPointerActions = true;
}
mTouchState.copyFrom(mTempTouchState);
} else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
@@ -1868,6 +1886,18 @@
return;
}
+ // If the motion event was modified in flight, then we cannot stream the sample.
+ if ((motionEventDispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_MASK)
+ != InputTarget::FLAG_DISPATCH_AS_IS) {
+#if DEBUG_BATCHING
+ LOGD("channel '%s' ~ Not streaming because the motion event was not "
+ "being dispatched as-is. "
+ "(Waiting for next dispatch cycle to start.)",
+ connection->getInputChannelName());
+#endif
+ return;
+ }
+
// The dispatch entry is in progress and is still potentially open for streaming.
// Try to stream the new motion sample. This might fail if the consumer has already
// consumed the motion event (or if the channel is broken).
@@ -1972,6 +2002,66 @@
dispatchEntry->headMotionSample = appendedMotionSample;
}
+ // Apply target flags and update the connection's input state.
+ switch (eventEntry->type) {
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+ dispatchEntry->resolvedAction = keyEntry->action;
+ dispatchEntry->resolvedFlags = keyEntry->flags;
+
+ if (!connection->inputState.trackKey(keyEntry,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
+ connection->getInputChannelName());
+#endif
+ return; // skip the inconsistent event
+ }
+ break;
+ }
+
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+ if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+ } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+ } else {
+ dispatchEntry->resolvedAction = motionEntry->action;
+ }
+ if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
+ && !connection->inputState.isHovering(
+ motionEntry->deviceId, motionEntry->source)) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
+ connection->getInputChannelName());
+#endif
+ dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ }
+
+ dispatchEntry->resolvedFlags = motionEntry->flags;
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+ dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ }
+
+ if (!connection->inputState.trackMotion(motionEntry,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
+ connection->getInputChannelName());
+#endif
+ return; // skip the inconsistent event
+ }
+ break;
+ }
+ }
+
// Enqueue the dispatch entry.
connection->outboundQueue.enqueueAtTail(dispatchEntry);
}
@@ -1999,16 +2089,11 @@
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
- // Apply target flags.
- int32_t action = keyEntry->action;
- int32_t flags = keyEntry->flags;
-
- // Update the connection's input state.
- connection->inputState.trackKey(keyEntry, action);
-
// Publish the key event.
- status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
- action, flags, keyEntry->keyCode, keyEntry->scanCode,
+ status = connection->inputPublisher.publishKeyEvent(
+ keyEntry->deviceId, keyEntry->source,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+ keyEntry->keyCode, keyEntry->scanCode,
keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
@@ -2024,24 +2109,6 @@
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
- // Apply target flags.
- int32_t action = motionEntry->action;
- int32_t flags = motionEntry->flags;
- if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- action = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
- action = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
- action = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
- action = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
- action = AMOTION_EVENT_ACTION_DOWN;
- }
- if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
- flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- }
-
// If headMotionSample is non-NULL, then it points to the first new sample that we
// were unable to dispatch during the previous cycle so we resume dispatching from
// that point in the list of motion samples.
@@ -2082,13 +2149,11 @@
}
}
- // Update the connection's input state.
- connection->inputState.trackMotion(motionEntry, action);
-
// Publish the motion event and the first motion sample.
- status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
- motionEntry->source, action, flags, motionEntry->edgeFlags,
- motionEntry->metaState, motionEntry->buttonState,
+ status = connection->inputPublisher.publishMotionEvent(
+ motionEntry->deviceId, motionEntry->source,
+ dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
+ motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, firstMotionSample->eventTime,
@@ -2102,8 +2167,8 @@
return;
}
- if (action == AMOTION_EVENT_ACTION_MOVE
- || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+ if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_MOVE
+ || dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
// Append additional motion samples.
MotionSample* nextMotionSample = firstMotionSample->next;
for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
@@ -2355,23 +2420,22 @@
break;
}
- int32_t xOffset, yOffset;
- float scaleFactor;
+ InputTarget target;
const InputWindow* window = getWindowLocked(connection->inputChannel);
if (window) {
- xOffset = -window->frameLeft;
- yOffset = -window->frameTop;
- scaleFactor = window->scaleFactor;
+ target.xOffset = -window->frameLeft;
+ target.yOffset = -window->frameTop;
+ target.scaleFactor = window->scaleFactor;
} else {
- xOffset = 0;
- yOffset = 0;
- scaleFactor = 1.0f;
+ target.xOffset = 0;
+ target.yOffset = 0;
+ target.scaleFactor = 1.0f;
}
+ target.inputChannel = connection->inputChannel;
+ target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
- DispatchEntry* cancelationDispatchEntry =
- mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
- 0, xOffset, yOffset, scaleFactor);
- connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
+ enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
+ &target, false, InputTarget::FLAG_DISPATCH_AS_IS);
mAllocator.releaseEventEntry(cancelationEventEntry);
}
@@ -3327,6 +3391,7 @@
resetTargetsLocked();
mTouchState.reset();
+ mLastHoverWindow = NULL;
}
void InputDispatcher::logDispatchStateLocked() {
@@ -4125,111 +4190,186 @@
return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
}
-void InputDispatcher::InputState::trackEvent(const EventEntry* entry, int32_t action) {
- switch (entry->type) {
- case EventEntry::TYPE_KEY:
- trackKey(static_cast<const KeyEntry*>(entry), action);
- break;
+bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source) const {
+ for (size_t i = 0; i < mMotionMementos.size(); i++) {
+ const MotionMemento& memento = mMotionMementos.itemAt(i);
+ if (memento.deviceId == deviceId
+ && memento.source == source
+ && memento.hovering) {
+ return true;
+ }
+ }
+ return false;
+}
- case EventEntry::TYPE_MOTION:
- trackMotion(static_cast<const MotionEntry*>(entry), action);
- break;
+bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
+ int32_t action, int32_t flags) {
+ switch (action) {
+ case AKEY_EVENT_ACTION_UP: {
+ if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+ for (size_t i = 0; i < mFallbackKeys.size(); ) {
+ if (mFallbackKeys.valueAt(i) == entry->keyCode) {
+ mFallbackKeys.removeItemsAt(i);
+ } else {
+ i += 1;
+ }
+ }
+ }
+ ssize_t index = findKeyMemento(entry);
+ if (index >= 0) {
+ mKeyMementos.removeAt(index);
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
+ "keyCode=%d, scanCode=%d",
+ entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
+#endif
+ return false;
+ }
+
+ case AKEY_EVENT_ACTION_DOWN: {
+ ssize_t index = findKeyMemento(entry);
+ if (index >= 0) {
+ mKeyMementos.removeAt(index);
+ }
+ addKeyMemento(entry, flags);
+ return true;
+ }
+
+ default:
+ return true;
}
}
-void InputDispatcher::InputState::trackKey(const KeyEntry* entry, int32_t action) {
- if (action == AKEY_EVENT_ACTION_UP
- && (entry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- for (size_t i = 0; i < mFallbackKeys.size(); ) {
- if (mFallbackKeys.valueAt(i) == entry->keyCode) {
- mFallbackKeys.removeItemsAt(i);
- } else {
- i += 1;
- }
+bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
+ int32_t action, int32_t flags) {
+ int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ switch (actionMasked) {
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.removeAt(index);
+ return true;
}
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
+ "actionMasked=%d",
+ entry->deviceId, entry->source, actionMasked);
+#endif
+ return false;
}
+ case AMOTION_EVENT_ACTION_DOWN: {
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.removeAt(index);
+ }
+ addMotionMemento(entry, flags, false /*hovering*/);
+ return true;
+ }
+
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ case AMOTION_EVENT_ACTION_MOVE: {
+ ssize_t index = findMotionMemento(entry, false /*hovering*/);
+ if (index >= 0) {
+ MotionMemento& memento = mMotionMementos.editItemAt(index);
+ memento.setPointers(entry);
+ return true;
+ }
+ if (actionMasked == AMOTION_EVENT_ACTION_MOVE
+ && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
+ | AINPUT_SOURCE_CLASS_NAVIGATION))) {
+ // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("Dropping inconsistent motion pointer up/down or move event: "
+ "deviceId=%d, source=%08x, actionMasked=%d",
+ entry->deviceId, entry->source, actionMasked);
+#endif
+ return false;
+ }
+
+ case AMOTION_EVENT_ACTION_HOVER_EXIT: {
+ ssize_t index = findMotionMemento(entry, true /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.removeAt(index);
+ return true;
+ }
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
+ entry->deviceId, entry->source);
+#endif
+ return false;
+ }
+
+ case AMOTION_EVENT_ACTION_HOVER_ENTER:
+ case AMOTION_EVENT_ACTION_HOVER_MOVE: {
+ ssize_t index = findMotionMemento(entry, true /*hovering*/);
+ if (index >= 0) {
+ mMotionMementos.removeAt(index);
+ }
+ addMotionMemento(entry, flags, true /*hovering*/);
+ return true;
+ }
+
+ default:
+ return true;
+ }
+}
+
+ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
for (size_t i = 0; i < mKeyMementos.size(); i++) {
- KeyMemento& memento = mKeyMementos.editItemAt(i);
+ const KeyMemento& memento = mKeyMementos.itemAt(i);
if (memento.deviceId == entry->deviceId
&& memento.source == entry->source
&& memento.keyCode == entry->keyCode
&& memento.scanCode == entry->scanCode) {
- switch (action) {
- case AKEY_EVENT_ACTION_UP:
- mKeyMementos.removeAt(i);
- return;
-
- case AKEY_EVENT_ACTION_DOWN:
- mKeyMementos.removeAt(i);
- goto Found;
-
- default:
- return;
- }
+ return i;
}
}
-
-Found:
- if (action == AKEY_EVENT_ACTION_DOWN) {
- mKeyMementos.push();
- KeyMemento& memento = mKeyMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.keyCode = entry->keyCode;
- memento.scanCode = entry->scanCode;
- memento.flags = entry->flags;
- memento.downTime = entry->downTime;
- }
+ return -1;
}
-void InputDispatcher::InputState::trackMotion(const MotionEntry* entry, int32_t action) {
- int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
+ bool hovering) const {
for (size_t i = 0; i < mMotionMementos.size(); i++) {
- MotionMemento& memento = mMotionMementos.editItemAt(i);
+ const MotionMemento& memento = mMotionMementos.itemAt(i);
if (memento.deviceId == entry->deviceId
- && memento.source == entry->source) {
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- case AMOTION_EVENT_ACTION_HOVER_EXIT:
- mMotionMementos.removeAt(i);
- return;
-
- case AMOTION_EVENT_ACTION_DOWN:
- mMotionMementos.removeAt(i);
- goto Found;
-
- case AMOTION_EVENT_ACTION_POINTER_UP:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_MOVE:
- memento.setPointers(entry);
- return;
-
- default:
- return;
- }
+ && memento.source == entry->source
+ && memento.hovering == hovering) {
+ return i;
}
}
+ return -1;
+}
-Found:
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- case AMOTION_EVENT_ACTION_HOVER_EXIT:
- mMotionMementos.push();
- MotionMemento& memento = mMotionMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.xPrecision = entry->xPrecision;
- memento.yPrecision = entry->yPrecision;
- memento.downTime = entry->downTime;
- memento.setPointers(entry);
- memento.hovering = actionMasked != AMOTION_EVENT_ACTION_DOWN;
- }
+void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
+ mKeyMementos.push();
+ KeyMemento& memento = mKeyMementos.editTop();
+ memento.deviceId = entry->deviceId;
+ memento.source = entry->source;
+ memento.keyCode = entry->keyCode;
+ memento.scanCode = entry->scanCode;
+ memento.flags = flags;
+ memento.downTime = entry->downTime;
+}
+
+void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
+ int32_t flags, bool hovering) {
+ mMotionMementos.push();
+ MotionMemento& memento = mMotionMementos.editTop();
+ memento.deviceId = entry->deviceId;
+ memento.source = entry->source;
+ memento.flags = flags;
+ memento.xPrecision = entry->xPrecision;
+ memento.yPrecision = entry->yPrecision;
+ memento.downTime = entry->downTime;
+ memento.setPointers(entry);
+ memento.hovering = hovering;
}
void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
@@ -4243,20 +4383,17 @@
void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
Allocator* allocator, Vector<EventEntry*>& outEvents,
const CancelationOptions& options) {
- for (size_t i = 0; i < mKeyMementos.size(); ) {
+ for (size_t i = 0; i < mKeyMementos.size(); i++) {
const KeyMemento& memento = mKeyMementos.itemAt(i);
if (shouldCancelKey(memento, options)) {
outEvents.push(allocator->obtainKeyEntry(currentTime,
memento.deviceId, memento.source, 0,
AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
- mKeyMementos.removeAt(i);
- } else {
- i += 1;
}
}
- for (size_t i = 0; i < mMotionMementos.size(); ) {
+ for (size_t i = 0; i < mMotionMementos.size(); i++) {
const MotionMemento& memento = mMotionMementos.itemAt(i);
if (shouldCancelMotion(memento, options)) {
outEvents.push(allocator->obtainMotionEntry(currentTime,
@@ -4264,12 +4401,9 @@
memento.hovering
? AMOTION_EVENT_ACTION_HOVER_EXIT
: AMOTION_EVENT_ACTION_CANCEL,
- 0, 0, 0, 0,
+ memento.flags, 0, 0, 0,
memento.xPrecision, memento.yPrecision, memento.downTime,
memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
- mMotionMementos.removeAt(i);
- } else {
- i += 1;
}
}
}
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 676d162..bdd1922 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -522,6 +522,10 @@
// True if dispatch has started.
bool inProgress;
+ // Set to the resolved action and flags when the event is enqueued.
+ int32_t resolvedAction;
+ int32_t resolvedFlags;
+
// For motion events:
// Pointer to the first motion sample to dispatch in this cycle.
// Usually NULL to indicate that the list of motion samples begins at
@@ -709,14 +713,19 @@
// Returns true if there is no state to be canceled.
bool isNeutral() const;
- // Records tracking information for an event that has just been published.
- void trackEvent(const EventEntry* entry, int32_t action);
+ // Returns true if the specified source is known to have received a hover enter
+ // motion event.
+ bool isHovering(int32_t deviceId, uint32_t source) const;
// Records tracking information for a key event that has just been published.
- void trackKey(const KeyEntry* entry, int32_t action);
+ // Returns true if the event should be delivered, false if it is inconsistent
+ // and should be skipped.
+ bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
// Records tracking information for a motion event that has just been published.
- void trackMotion(const MotionEntry* entry, int32_t action);
+ // Returns true if the event should be delivered, false if it is inconsistent
+ // and should be skipped.
+ bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
// Synthesizes cancelation events for the current state and resets the tracked state.
void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
@@ -756,6 +765,7 @@
struct MotionMemento {
int32_t deviceId;
uint32_t source;
+ int32_t flags;
float xPrecision;
float yPrecision;
nsecs_t downTime;
@@ -771,6 +781,12 @@
Vector<MotionMemento> mMotionMementos;
KeyedVector<int32_t, int32_t> mFallbackKeys;
+ ssize_t findKeyMemento(const KeyEntry* entry) const;
+ ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
+
+ void addKeyMemento(const KeyEntry* entry, int32_t flags);
+ void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
+
static bool shouldCancelKey(const KeyMemento& memento,
const CancelationOptions& options);
static bool shouldCancelMotion(const MotionMemento& memento,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3e4c666..82c3af3 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -53,6 +53,7 @@
#define INDENT2 " "
#define INDENT3 " "
#define INDENT4 " "
+#define INDENT5 " "
namespace android {
@@ -154,14 +155,15 @@
case BTN_LEFT:
return AMOTION_EVENT_BUTTON_PRIMARY;
case BTN_RIGHT:
+ case BTN_STYLUS:
return AMOTION_EVENT_BUTTON_SECONDARY;
case BTN_MIDDLE:
+ case BTN_STYLUS2:
return AMOTION_EVENT_BUTTON_TERTIARY;
case BTN_SIDE:
return AMOTION_EVENT_BUTTON_BACK;
- case BTN_EXTRA:
- return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_FORWARD:
+ case BTN_EXTRA:
return AMOTION_EVENT_BUTTON_FORWARD;
case BTN_BACK:
return AMOTION_EVENT_BUTTON_BACK;
@@ -176,8 +178,7 @@
static bool isPointerDown(int32_t buttonState) {
return buttonState &
(AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
- | AMOTION_EVENT_BUTTON_TERTIARY
- | AMOTION_EVENT_BUTTON_ERASER);
+ | AMOTION_EVENT_BUTTON_TERTIARY);
}
static int32_t calculateEdgeFlagsUsingPointerBounds(
@@ -921,7 +922,7 @@
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
#if DEBUG_RAW_EVENTS
LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
- "keycode=0x%04x value=0x%04x flags=0x%08x",
+ "keycode=0x%04x value=0x%08x flags=0x%08x",
rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
rawEvent->value, rawEvent->flags);
#endif
@@ -1921,8 +1922,17 @@
dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale);
dump.appendFormat(INDENT3 "Last Touch:\n");
- dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
+ dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
+ for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) {
+ const PointerData& pointer = mLastTouch.pointers[i];
+ dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
+ "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
+ "orientation=%d, distance=%d, isStylus=%s\n", i,
+ pointer.id, pointer.x, pointer.y, pointer.pressure,
+ pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
+ pointer.orientation, pointer.distance, toString(pointer.isStylus));
+ }
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
@@ -3704,6 +3714,29 @@
mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
mPointerGesture.currentGestureIdBits, -1,
0, 0, mPointerGesture.downTime);
+ } else if (dispatchedGestureIdBits.isEmpty()
+ && !mPointerGesture.lastGestureIdBits.isEmpty()) {
+ // Synthesize a hover move event after all pointers go up to indicate that
+ // the pointer is hovering again even if the user is not currently touching
+ // the touch pad. This ensures that a view will receive a fresh hover enter
+ // event after a tap.
+ float x, y;
+ mPointerController->getPosition(&x, &y);
+
+ PointerProperties pointerProperties;
+ pointerProperties.clear();
+ pointerProperties.id = 0;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+
+ PointerCoords pointerCoords;
+ pointerCoords.clear();
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
+ pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+
+ getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags,
+ AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
}
// Update state.
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 08cc75e..0ae2ab8 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -252,11 +252,7 @@
| DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
status_t status;
if (!haveTransaction) {
- status = mSurfaceComposerClient->openTransaction();
- if (status) {
- LOGE("Error %d opening transation to update sprite surface.", status);
- break;
- }
+ SurfaceComposerClient::openGlobalTransaction();
haveTransaction = true;
}
@@ -322,10 +318,7 @@
}
if (haveTransaction) {
- status_t status = mSurfaceComposerClient->closeTransaction();
- if (status) {
- LOGE("Error %d closing transaction to update sprite surface.", status);
- }
+ SurfaceComposerClient::closeGlobalTransaction();
}
// If any surfaces were changed, write back the new surface properties to the sprites.
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 8c07e15..5e54d61 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -255,10 +255,7 @@
// Update the kernel timezone information
// Kernel tracks time offsets as 'minutes west of GMT'
- int gmtOffset = zone.getRawOffset();
- if (zone.inDaylightTime(new Date(System.currentTimeMillis()))) {
- gmtOffset += zone.getDSTSavings();
- }
+ int gmtOffset = zone.getOffset(System.currentTimeMillis());
setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
}
@@ -759,9 +756,8 @@
// based off of the current Zone gmt offset + userspace tracked
// daylight savings information.
TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
- int gmtOffset = (zone.getRawOffset() + zone.getDSTSavings()) / 60000;
-
- setKernelTimezone(mDescriptor, -(gmtOffset));
+ int gmtOffset = zone.getOffset(System.currentTimeMillis());
+ setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
scheduleDateChangedEvent();
}
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 07855d9..8fb6274 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -19,7 +19,7 @@
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.ContentResolver;
@@ -71,6 +71,7 @@
import com.android.server.connectivity.Vpn;
import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -78,8 +79,10 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.GregorianCalendar;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -108,8 +111,12 @@
private Vpn mVpn;
+ /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
+ private Object mRulesLock = new Object();
/** Currently active network rules by UID. */
private SparseIntArray mUidRules = new SparseIntArray();
+ /** Set of ifaces that are costly. */
+ private HashSet<String> mMeteredIfaces = Sets.newHashSet();
/**
* Sometimes we want to refer to the individual network state
@@ -124,8 +131,6 @@
*/
private List mNetRequestersPids[];
- private WifiWatchdogService mWifiWatchdogService;
-
// priority order of the nettrackers
// (excluding dynamically set mNetworkPreference)
// TODO - move mNetworkTypePreference into this
@@ -271,6 +276,9 @@
}
RadioAttributes[] mRadioAttributes;
+ // the set of network types that can only be enabled by system/sig apps
+ List mProtectedNetworks;
+
public ConnectivityService(
Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
if (DBG) log("ConnectivityService starting up");
@@ -374,6 +382,17 @@
}
}
+ mProtectedNetworks = new ArrayList<Integer>();
+ int[] protectedNetworks = context.getResources().getIntArray(
+ com.android.internal.R.array.config_protectedNetworks);
+ for (int p : protectedNetworks) {
+ if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
+ mProtectedNetworks.add(p);
+ } else {
+ if (DBG) loge("Ignoring protectedNetwork " + p);
+ }
+ }
+
// high priority first
mPriorityList = new int[mNetworksDefined];
{
@@ -425,10 +444,6 @@
wifiService.checkAndStartWifi();
mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
wst.startMonitoring(context, mHandler);
-
- //TODO: as part of WWS refactor, create only when needed
- mWifiWatchdogService = new WifiWatchdogService(context);
-
break;
case ConnectivityManager.TYPE_MOBILE:
mNetTrackers[netType] = new MobileDataStateTracker(netType,
@@ -459,12 +474,10 @@
INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
- mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
- !mTethering.isDunRequired()) &&
- (mTethering.getTetherableUsbRegexs().length != 0 ||
+ mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
mTethering.getTetherableWifiRegexs().length != 0 ||
mTethering.getTetherableBluetoothRegexs().length != 0) &&
- mTethering.getUpstreamIfaceRegexs().length != 0);
+ mTethering.getUpstreamIfaceTypes().length != 0);
mVpn = new Vpn(mContext, new VpnCallback());
@@ -570,31 +583,35 @@
}
/**
- * Check if UID is blocked from using the given {@link NetworkInfo}.
+ * Check if UID should be blocked from using the network represented by the
+ * given {@link NetworkStateTracker}.
*/
- private boolean isNetworkBlocked(NetworkInfo info, int uid) {
- synchronized (mUidRules) {
- // TODO: expand definition of "paid" network to cover tethered or
- // paid hotspot use cases.
- final boolean networkIsPaid = info.getType() != ConnectivityManager.TYPE_WIFI;
- final int uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+ private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) {
+ final String iface = tracker.getLinkProperties().getInterfaceName();
- if (networkIsPaid && (uidRules & RULE_REJECT_PAID) != 0) {
- return true;
- }
-
- // no restrictive rules; network is visible
- return false;
+ final boolean networkCostly;
+ final int uidRules;
+ synchronized (mRulesLock) {
+ networkCostly = mMeteredIfaces.contains(iface);
+ uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
+
+ if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) {
+ return true;
+ }
+
+ // no restrictive rules; network is visible
+ return false;
}
/**
- * Return a filtered version of the given {@link NetworkInfo}, potentially
- * marked {@link DetailedState#BLOCKED} based on
- * {@link #isNetworkBlocked(NetworkInfo, int)}.
+ * Return a filtered {@link NetworkInfo}, potentially marked
+ * {@link DetailedState#BLOCKED} based on
+ * {@link #isNetworkBlocked(NetworkStateTracker, int)}.
*/
- private NetworkInfo filterNetworkInfo(NetworkInfo info, int uid) {
- if (isNetworkBlocked(info, uid)) {
+ private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) {
+ NetworkInfo info = tracker.getNetworkInfo();
+ if (isNetworkBlocked(tracker, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
@@ -634,7 +651,7 @@
if (isNetworkTypeValid(networkType)) {
final NetworkStateTracker tracker = mNetTrackers[networkType];
if (tracker != null) {
- info = filterNetworkInfo(tracker.getNetworkInfo(), uid);
+ info = getFilteredNetworkInfo(tracker, uid);
}
}
return info;
@@ -645,10 +662,10 @@
enforceAccessPermission();
final int uid = Binder.getCallingUid();
final ArrayList<NetworkInfo> result = Lists.newArrayList();
- synchronized (mUidRules) {
+ synchronized (mRulesLock) {
for (NetworkStateTracker tracker : mNetTrackers) {
if (tracker != null) {
- result.add(filterNetworkInfo(tracker.getNetworkInfo(), uid));
+ result.add(getFilteredNetworkInfo(tracker, uid));
}
}
}
@@ -685,10 +702,10 @@
enforceAccessPermission();
final int uid = Binder.getCallingUid();
final ArrayList<NetworkState> result = Lists.newArrayList();
- synchronized (mUidRules) {
+ synchronized (mRulesLock) {
for (NetworkStateTracker tracker : mNetTrackers) {
if (tracker != null) {
- final NetworkInfo info = filterNetworkInfo(tracker.getNetworkInfo(), uid);
+ final NetworkInfo info = getFilteredNetworkInfo(tracker, uid);
result.add(new NetworkState(
info, tracker.getLinkProperties(), tracker.getLinkCapabilities()));
}
@@ -793,6 +810,11 @@
usedNetworkType = networkType;
}
}
+
+ if (mProtectedNetworks.contains(usedNetworkType)) {
+ enforceConnectivityInternalPermission();
+ }
+
NetworkStateTracker network = mNetTrackers[usedNetworkType];
if (network != null) {
Integer currentPid = new Integer(getCallingPid());
@@ -1003,6 +1025,10 @@
*/
public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
enforceChangePermission();
+ if (mProtectedNetworks.contains(networkType)) {
+ enforceConnectivityInternalPermission();
+ }
+
if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
return false;
}
@@ -1120,7 +1146,8 @@
}
public void setDataDependency(int networkType, boolean met) {
- enforceChangePermission();
+ enforceConnectivityInternalPermission();
+
if (DBG) {
log("setDataDependency(" + networkType + ", " + met + ")");
}
@@ -1139,15 +1166,15 @@
private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
@Override
- public void onRulesChanged(int uid, int uidRules) {
+ public void onUidRulesChanged(int uid, int uidRules) {
// only someone like NPMS should only be calling us
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
if (LOGD_RULES) {
- Slog.d(TAG, "onRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
+ Slog.d(TAG, "onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
}
- synchronized (mUidRules) {
+ synchronized (mRulesLock) {
// skip update when we've already applied rules
final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
if (oldRules == uidRules) return;
@@ -1158,6 +1185,24 @@
// TODO: dispatch into NMS to push rules towards kernel module
// TODO: notify UID when it has requested targeted updates
}
+
+ @Override
+ public void onMeteredIfacesChanged(String[] meteredIfaces) {
+ // only someone like NPMS should only be calling us
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ if (LOGD_RULES) {
+ Slog.d(TAG,
+ "onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
+ }
+
+ synchronized (mRulesLock) {
+ mMeteredIfaces.clear();
+ for (String iface : meteredIfaces) {
+ mMeteredIfaces.add(iface);
+ }
+ }
+ }
};
/**
@@ -1547,12 +1592,6 @@
}
addPrivateDnsRoutes(mNetTrackers[netType]);
}
-
- /** Notify TetheringService if interface name has been changed. */
- if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
- Phone.REASON_LINK_PROPERTIES_CHANGED)) {
- handleTetherIfaceChange(netType);
- }
} else {
if (mNetConfigs[netType].isDefault()) {
removeDefaultRoute(mNetTrackers[netType]);
@@ -1571,6 +1610,16 @@
}
}
}
+
+ // TODO: Temporary notifying upstread change to Tethering.
+ // @see bug/4455071
+ /** Notify TetheringService if interface name has been changed. */
+ if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
+ Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+ if (isTetheringSupported()) {
+ mTethering.handleTetherIfaceChange();
+ }
+ }
}
private void addPrivateDnsRoutes(NetworkStateTracker nt) {
@@ -1996,7 +2045,10 @@
break;
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
info = (NetworkInfo) msg.obj;
- handleConnectivityChange(info.getType(), true);
+ // TODO: Temporary allowing network configuration
+ // change not resetting sockets.
+ // @see bug/4455071
+ handleConnectivityChange(info.getType(), false);
break;
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
String causedBy = null;
@@ -2383,14 +2435,6 @@
}
}
- private void handleTetherIfaceChange(int type) {
- String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();
-
- if (isTetheringSupported()) {
- mTethering.handleTetherIfaceChange(iface);
- }
- }
-
private void log(String s) {
Slog.d(TAG, s);
}
diff --git a/services/java/com/android/server/DnsPinger.java b/services/java/com/android/server/DnsPinger.java
new file mode 100644
index 0000000..4e33938
--- /dev/null
+++ b/services/java/com/android/server/DnsPinger.java
@@ -0,0 +1,228 @@
+/*
+ * 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.server;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketTimeoutException;
+import java.util.Collection;
+import java.util.Random;
+
+/**
+ * Performs a simple DNS "ping" by sending a "server status" query packet to the
+ * DNS server. As long as the server replies, we consider it a success.
+ * <p>
+ * We do not use a simple hostname lookup because that could be cached and the
+ * API may not differentiate between a time out and a failure lookup (which we
+ * really care about).
+ * <p>
+ * TODO : More general API. Socket does not bind to specified connection type
+ * TODO : Choice of DNS query location - current looks up www.android.com
+ *
+ * @hide
+ */
+public final class DnsPinger {
+ private static final boolean V = true;
+
+ /** Number of bytes for the query */
+ private static final int DNS_QUERY_BASE_SIZE = 32;
+
+ /** The DNS port */
+ private static final int DNS_PORT = 53;
+
+ /** Used to generate IDs */
+ private static Random sRandom = new Random();
+
+ private ConnectivityManager mConnectivityManager = null;
+ private Context mContext;
+ private int mConnectionType;
+ private InetAddress mDefaultDns;
+
+ private String TAG;
+
+ /**
+ * @param connectionType The connection type from {@link ConnectivityManager}
+ */
+ public DnsPinger(String TAG, Context context, int connectionType) {
+ mContext = context;
+ mConnectionType = connectionType;
+ if (!ConnectivityManager.isNetworkTypeValid(connectionType)) {
+ Slog.e(TAG, "Invalid connectionType in constructor: " + connectionType);
+ }
+ this.TAG = TAG;
+
+ mDefaultDns = getDefaultDns();
+ }
+
+ /**
+ * @return The first DNS in the link properties of the specified connection
+ * type or the default system DNS if the link properties has null
+ * dns set. Should not be null.
+ */
+ public InetAddress getDns() {
+ LinkProperties curLinkProps = getCurrentLinkProperties();
+ if (curLinkProps == null) {
+ Slog.e(TAG, "getCurLinkProperties:: LP for type" + mConnectionType + " is null!");
+ return mDefaultDns;
+ }
+
+ Collection<InetAddress> dnses = curLinkProps.getDnses();
+ if (dnses == null || dnses.size() == 0) {
+ Slog.v(TAG, "getDns::LinkProps has null dns - returning default");
+ return mDefaultDns;
+ }
+
+ return dnses.iterator().next();
+ }
+
+ private LinkProperties getCurrentLinkProperties() {
+ if (mConnectivityManager == null) {
+ mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ }
+
+ return mConnectivityManager.getLinkProperties(mConnectionType);
+ }
+
+ private InetAddress getDefaultDns() {
+ String dns = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.DEFAULT_DNS_SERVER);
+ if (dns == null || dns.length() == 0) {
+ dns = mContext.getResources().getString(
+ com.android.internal.R.string.config_default_dns_server);
+ }
+ try {
+ return NetworkUtils.numericToInetAddress(dns);
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "getDefaultDns::malformed default dns address");
+ return null;
+ }
+ }
+
+ /**
+ * @return time to response. Negative value on error.
+ */
+ public long pingDns(InetAddress dnsAddress, int timeout) {
+ DatagramSocket socket = null;
+ try {
+ socket = new DatagramSocket();
+
+ // Set some socket properties
+ socket.setSoTimeout(timeout);
+
+ // Try to bind but continue ping if bind fails
+ try {
+ socket.setNetworkInterface(NetworkInterface.getByName(
+ getCurrentLinkProperties().getInterfaceName()));
+ } catch (Exception e) {
+ Slog.d(TAG,"pingDns::Error binding to socket", e);
+ }
+
+ byte[] buf = constructQuery();
+
+ // Send the DNS query
+
+ DatagramPacket packet = new DatagramPacket(buf,
+ buf.length, dnsAddress, DNS_PORT);
+ long start = SystemClock.elapsedRealtime();
+ socket.send(packet);
+
+ // Wait for reply (blocks for the above timeout)
+ DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
+ socket.receive(replyPacket);
+
+ // If a timeout occurred, an exception would have been thrown. We
+ // got a reply!
+ return SystemClock.elapsedRealtime() - start;
+
+ } catch (SocketTimeoutException e) {
+ // Squelch this exception.
+ return -1;
+ } catch (Exception e) {
+ if (V) {
+ Slog.v(TAG, "DnsPinger.pingDns got socket exception: ", e);
+ }
+ return -2;
+ } finally {
+ if (socket != null) {
+ socket.close();
+ }
+ }
+
+ }
+
+ /**
+ * @return google.com DNS query packet
+ */
+ private static byte[] constructQuery() {
+ byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
+
+ // [0-1] bytes are an ID, generate random ID for this query
+ buf[0] = (byte) sRandom.nextInt(256);
+ buf[1] = (byte) sRandom.nextInt(256);
+
+ // [2-3] bytes are for flags.
+ buf[2] = 0x01; // Recursion desired
+
+ // [4-5] bytes are for number of queries (QCOUNT)
+ buf[5] = 0x01;
+
+ // [6-7] [8-9] [10-11] are all counts of other fields we don't use
+
+ // [12-15] for www
+ writeString(buf, 12, "www");
+
+ // [16-22] for google
+ writeString(buf, 16, "google");
+
+ // [23-26] for com
+ writeString(buf, 23, "com");
+
+ // [27] is a null byte terminator byte for the url
+
+ // [28-29] bytes are for QTYPE, set to 1 = A (host address)
+ buf[29] = 0x01;
+
+ // [30-31] bytes are for QCLASS, set to 1 = IN (internet)
+ buf[31] = 0x01;
+
+ return buf;
+ }
+
+ /**
+ * Writes the string's length and its contents to the buffer
+ */
+ private static void writeString(byte[] buf, int startPos, String string) {
+ int pos = startPos;
+
+ // Write the length first
+ buf[pos++] = (byte) string.length();
+ for (int i = 0; i < string.length(); i++) {
+ buf[pos++] = (byte) string.charAt(i);
+ }
+ }
+}
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index fbde9d1..14abf80 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -35,6 +35,8 @@
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -52,6 +54,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
+import android.graphics.BitmapFactory;
import android.inputmethodservice.InputMethodService;
import android.os.Binder;
import android.os.Environment;
@@ -134,6 +137,7 @@
private static final String NOT_A_SUBTYPE_ID_STR = String.valueOf(NOT_A_SUBTYPE_ID);
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
private static final String SUBTYPE_MODE_VOICE = "voice";
+ private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
final Context mContext;
final Resources mRes;
@@ -154,6 +158,13 @@
private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
+ // Ongoing notification
+ private final NotificationManager mNotificationManager;
+ private final Notification mImeSwitcherNotification;
+ private final PendingIntent mImeSwitchPendingIntent;
+ private final boolean mShowOngoingImeSwitcherForPhones;
+ private boolean mNotificationShown;
+
class SessionState {
final ClientState client;
final IInputMethod method;
@@ -508,6 +519,25 @@
handleMessage(msg);
}
});
+
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ mImeSwitcherNotification = new Notification();
+ mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
+ mImeSwitcherNotification.when = 0;
+ mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
+ mImeSwitcherNotification.tickerText = null;
+ mImeSwitcherNotification.defaults = 0; // please be quiet
+ mImeSwitcherNotification.sound = null;
+ mImeSwitcherNotification.vibrate = null;
+ Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mImeSwitchPendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+ mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
+ com.android.internal.R.bool.show_ongoing_ime_switcher);
+
synchronized (mMethodMap) {
mFileManager = new InputMethodFileManager(mMethodMap);
}
@@ -522,6 +552,7 @@
mStatusBar = statusBar;
statusBar.setIconVisibility("ime", false);
+ mNotificationShown = false;
// mSettings should be created before buildInputMethodListLocked
mSettings = new InputMethodSettings(
@@ -1022,6 +1053,51 @@
}
}
+ private boolean needsToShowImeSwitchOngoingNotification() {
+ if (!mShowOngoingImeSwitcherForPhones) return false;
+ synchronized (mMethodMap) {
+ List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
+ final int N = imis.size();
+ if (N > 2) return true;
+ if (N < 1) return false;
+ int nonAuxCount = 0;
+ int auxCount = 0;
+ InputMethodSubtype nonAuxSubtype = null;
+ InputMethodSubtype auxSubtype = null;
+ for(int i = 0; i < N; ++i) {
+ final InputMethodInfo imi = imis.get(i);
+ final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeListLocked(
+ imi, true);
+ final int subtypeCount = subtypes.size();
+ if (subtypeCount == 0) {
+ ++nonAuxCount;
+ } else {
+ for (int j = 0; j < subtypeCount; ++j) {
+ final InputMethodSubtype subtype = subtypes.get(j);
+ if (!subtype.isAuxiliary()) {
+ ++nonAuxCount;
+ nonAuxSubtype = subtype;
+ } else {
+ ++auxCount;
+ auxSubtype = subtype;
+ }
+ }
+ }
+ }
+ if (nonAuxCount > 1 || auxCount > 1) {
+ return true;
+ } else if (nonAuxCount == 1 && auxCount == 1) {
+ if (nonAuxSubtype != null && auxSubtype != null
+ && nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
+ && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+
@Override
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
int uid = Binder.getCallingUid();
@@ -1036,6 +1112,25 @@
mImeWindowVis = vis;
mBackDisposition = backDisposition;
mStatusBar.setImeWindowStatus(token, vis, backDisposition);
+ final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0;
+ if (iconVisibility && needsToShowImeSwitchOngoingNotification()) {
+ final PackageManager pm = mContext.getPackageManager();
+ final CharSequence label = mMethodMap.get(mCurMethodId).loadLabel(pm);
+ final CharSequence title = mRes.getText(
+ com.android.internal.R.string.select_input_method);
+ mImeSwitcherNotification.setLatestEventInfo(
+ mContext, title, label, mImeSwitchPendingIntent);
+ mNotificationManager.notify(
+ com.android.internal.R.string.select_input_method,
+ mImeSwitcherNotification);
+ mNotificationShown = true;
+ } else {
+ if (mNotificationShown) {
+ mNotificationManager.cancel(
+ com.android.internal.R.string.select_input_method);
+ mNotificationShown = false;
+ }
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1546,7 +1641,7 @@
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
if (imi == null) return false;
final int N = subtypes.length;
- mFileManager.addInputMethodSubtypes(mCurMethodId, subtypes);
+ mFileManager.addInputMethodSubtypes(imi, subtypes);
buildInputMethodListLocked(mMethodList, mMethodMap);
return true;
}
@@ -1928,25 +2023,26 @@
final CharSequence label = imi.loadLabel(pm);
if (showSubtypes && enabledSubtypeSet.size() > 0) {
final int subtypeCount = imi.getSubtypeCount();
+ if (DEBUG) {
+ Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId());
+ }
for (int j = 0; j < subtypeCount; ++j) {
- InputMethodSubtype subtype = imi.getSubtypeAt(j);
- if (enabledSubtypeSet.contains(String.valueOf(subtype.hashCode()))
- && !subtype.isAuxiliary()) {
+ final InputMethodSubtype subtype = imi.getSubtypeAt(j);
+ final String subtypeHashCode = String.valueOf(subtype.hashCode());
+ // We show all enabled IMEs and subtypes when an IME is shown.
+ if (enabledSubtypeSet.contains(subtypeHashCode)
+ && (mInputShown || !subtype.isAuxiliary())) {
final CharSequence title;
- int nameResId = subtype.getNameResId();
- String mode = subtype.getMode();
- if (nameResId != 0) {
- title = TextUtils.concat(subtype.getDisplayName(context,
- imi.getPackageName(), imi.getServiceInfo().applicationInfo),
- (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
- } else {
- CharSequence language = subtype.getLocale();
- // TODO: Use more friendly Title and UI
- title = label + "," + (mode == null ? "" : mode) + ","
- + (language == null ? "" : language);
- }
+ final String mode = subtype.getMode();
+ title = TextUtils.concat(subtype.getDisplayName(context,
+ imi.getPackageName(), imi.getServiceInfo().applicationInfo),
+ (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
imList.add(new Pair<CharSequence, Pair<InputMethodInfo, Integer>>(
title, new Pair<InputMethodInfo, Integer>(imi, j)));
+ // Removing this subtype from enabledSubtypeSet because we no longer
+ // need to add an entry of this subtype to imList to avoid duplicated
+ // entries.
+ enabledSubtypeSet.remove(subtypeHashCode);
}
}
} else {
@@ -2243,7 +2339,7 @@
}
}
}
- ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
+ final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
applicableModeAndSubtypesMap.values());
if (!containsKeyboardSubtype) {
InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
@@ -2921,17 +3017,23 @@
}
public void addInputMethodSubtypes(
- String imiId, InputMethodSubtype[] additionalSubtypes) {
+ InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
synchronized (mMethodMap) {
+ final HashSet<InputMethodSubtype> existingSubtypes =
+ new HashSet<InputMethodSubtype>();
+ for (int i = 0; i < imi.getSubtypeCount(); ++i) {
+ existingSubtypes.add(imi.getSubtypeAt(i));
+ }
+
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
final int N = additionalSubtypes.length;
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = additionalSubtypes[i];
- if (!subtypes.contains(subtype)) {
+ if (!subtypes.contains(subtype) && !existingSubtypes.contains(subtype)) {
subtypes.add(subtype);
}
}
- mSubtypesMap.put(imiId, subtypes);
+ mSubtypesMap.put(imi.getId(), subtypes);
writeAdditionalInputMethodSubtypes(mSubtypesMap, mAdditionalInputMethodSubtypeFile,
mMethodMap);
}
@@ -3038,8 +3140,8 @@
parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
final String imeSubtypeExtraValue =
parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
- final boolean isAuxiliary =
- Boolean.valueOf(parser.getAttributeValue(null, ATTR_IS_AUXILIARY));
+ final boolean isAuxiliary = "1".equals(String.valueOf(
+ parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
final InputMethodSubtype subtype =
new InputMethodSubtype(label, icon, imeSubtypeLocale,
imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index 1d3e3ac..b3d7220 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -41,7 +41,7 @@
/**
* {@hide}
*/
-public class IntentResolver<F extends IntentFilter, R extends Object> {
+public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
final private static String TAG = "IntentResolver";
final private static boolean DEBUG = false;
final private static boolean localLOGV = DEBUG || false;
@@ -333,14 +333,19 @@
return false;
}
- protected String packageForFilter(F filter) {
- return null;
- }
+ /**
+ * Return the package that owns this filter. This must be implemented to
+ * provide correct filtering of Intents that have specified a package name
+ * they are to be delivered to.
+ */
+ protected abstract String packageForFilter(F filter);
+ @SuppressWarnings("unchecked")
protected R newResult(F filter, int match) {
return (R)filter;
}
+ @SuppressWarnings("unchecked")
protected void sortResults(List<R> results) {
Collections.sort(results, mResolvePrioritySorter);
}
@@ -502,6 +507,7 @@
String resolvedType, String scheme, List<F> src, List<R> dest) {
final String action = intent.getAction();
final Uri data = intent.getData();
+ final String packageName = intent.getPackage();
final boolean excludingStopped = intent.isExcludingStopped();
@@ -520,6 +526,14 @@
continue;
}
+ // Is delivery being limited to filters owned by a particular package?
+ if (packageName != null && !packageName.equals(packageForFilter(filter))) {
+ if (debug) {
+ Slog.v(TAG, " Filter is not from package " + packageName + "; skipping");
+ }
+ continue;
+ }
+
// Do we already have this one?
if (!allowFilterResult(filter, dest)) {
if (debug) {
@@ -561,6 +575,7 @@
}
// Sorts a List of IntentFilter objects into descending priority order.
+ @SuppressWarnings("rawtypes")
private static final Comparator mResolvePrioritySorter = new Comparator() {
public int compare(Object o1, Object o2) {
final int q1 = ((IntentFilter) o1).getPriority();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 656ec4d..56afe7f 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -195,6 +195,7 @@
final Object mKey;
final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
int mPendingBroadcasts;
+ String requiredPermissions;
Receiver(ILocationListener listener) {
mListener = listener;
@@ -284,7 +285,8 @@
synchronized (this) {
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
- mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
+ mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
+ requiredPermissions);
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -319,7 +321,8 @@
synchronized (this) {
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
- mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
+ mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
+ requiredPermissions);
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -358,7 +361,8 @@
synchronized (this) {
// synchronize to ensure incrementPendingBroadcastsLocked()
// is called before decrementPendingBroadcasts()
- mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
+ mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
+ requiredPermissions);
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcastsLocked();
@@ -572,22 +576,30 @@
return Settings.Secure.isLocationProviderEnabled(resolver, provider);
}
- private void checkPermissionsSafe(String provider) {
- if ((LocationManager.GPS_PROVIDER.equals(provider)
- || LocationManager.PASSIVE_PROVIDER.equals(provider))
- && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- throw new SecurityException("Provider " + provider
- + " requires ACCESS_FINE_LOCATION permission");
+ private String checkPermissionsSafe(String provider, String lastPermission) {
+ if (LocationManager.GPS_PROVIDER.equals(provider)
+ || LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+ if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Provider " + provider
+ + " requires ACCESS_FINE_LOCATION permission");
+ }
+ return ACCESS_FINE_LOCATION;
}
- if (LocationManager.NETWORK_PROVIDER.equals(provider)
- && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)
- && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- throw new SecurityException("Provider " + provider
- + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
+
+ // Assume any other provider requires the coarse or fine permission.
+ if (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
+ == PackageManager.PERMISSION_GRANTED) {
+ return ACCESS_FINE_LOCATION.equals(lastPermission)
+ ? lastPermission : ACCESS_COARSE_LOCATION;
}
+ if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
+ == PackageManager.PERMISSION_GRANTED) {
+ return ACCESS_FINE_LOCATION;
+ }
+
+ throw new SecurityException("Provider " + provider
+ + " requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
}
private boolean isAllowedProviderSafe(String provider) {
@@ -1099,8 +1111,21 @@
}
}
+ void validatePendingIntent(PendingIntent intent) {
+ if (intent.isTargetedToPackage()) {
+ return;
+ }
+ Slog.i(TAG, "Given Intent does not require a specific package: "
+ + intent);
+ // XXX we should really throw a security exception, if the caller's
+ // targetSdkVersion is high enough.
+ //throw new SecurityException("Given Intent does not require a specific package: "
+ // + intent);
+ }
+
public void requestLocationUpdatesPI(String provider, Criteria criteria,
long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
+ validatePendingIntent(intent);
if (criteria != null) {
// FIXME - should we consider using multiple providers simultaneously
// rather than only the best one?
@@ -1132,7 +1157,8 @@
throw new IllegalArgumentException("provider=" + provider);
}
- checkPermissionsSafe(provider);
+ receiver.requiredPermissions = checkPermissionsSafe(provider,
+ receiver.requiredPermissions);
// so wakelock calls will succeed
final int callingUid = Binder.getCallingUid();
@@ -1300,7 +1326,7 @@
}
// first check for permission to the provider
- checkPermissionsSafe(provider);
+ checkPermissionsSafe(provider, null);
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
!= PackageManager.PERMISSION_GRANTED)) {
@@ -1432,7 +1458,8 @@
synchronized (this) {
// synchronize to ensure incrementPendingBroadcasts()
// is called before decrementPendingBroadcasts()
- intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
+ intent.send(mContext, 0, enteredIntent, this, mLocationHandler,
+ ACCESS_FINE_LOCATION);
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcasts();
@@ -1457,7 +1484,8 @@
synchronized (this) {
// synchronize to ensure incrementPendingBroadcasts()
// is called before decrementPendingBroadcasts()
- intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
+ intent.send(mContext, 0, exitedIntent, this, mLocationHandler,
+ ACCESS_FINE_LOCATION);
// call this after broadcasting so we do not increment
// if we throw an exeption.
incrementPendingBroadcasts();
@@ -1526,6 +1554,7 @@
public void addProximityAlert(double latitude, double longitude,
float radius, long expiration, PendingIntent intent) {
+ validatePendingIntent(intent);
try {
synchronized (mLock) {
addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
@@ -1626,7 +1655,7 @@
return null;
}
- checkPermissionsSafe(provider);
+ checkPermissionsSafe(provider, null);
Bundle b = new Bundle();
b.putBoolean("network", p.requiresNetwork());
@@ -1668,7 +1697,7 @@
}
private boolean _isProviderEnabledLocked(String provider) {
- checkPermissionsSafe(provider);
+ checkPermissionsSafe(provider, null);
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
@@ -1694,7 +1723,7 @@
}
private Location _getLastKnownLocationLocked(String provider) {
- checkPermissionsSafe(provider);
+ checkPermissionsSafe(provider, null);
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index c86f962..54e5432 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -33,6 +33,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.hardware.usb.UsbManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
@@ -152,7 +153,6 @@
* 600 series - Unsolicited broadcasts.
*/
public static final int VolumeStateChange = 605;
- public static final int ShareAvailabilityChange = 620;
public static final int VolumeDiskInserted = 630;
public static final int VolumeDiskRemoved = 631;
public static final int VolumeBadRemoval = 632;
@@ -167,6 +167,7 @@
private String mExternalStoragePath;
private PackageManagerService mPms;
private boolean mUmsEnabling;
+ private boolean mUmsAvailable = false;
// Used as a lock for methods that register/unregister listeners.
final private ArrayList<MountServiceBinderListener> mListeners =
new ArrayList<MountServiceBinderListener>();
@@ -525,6 +526,10 @@
}
}
}.start();
+ } else if (action.equals(UsbManager.ACTION_USB_STATE)) {
+ boolean available = (intent.getBooleanExtra(UsbManager.USB_CONNECTED, false) &&
+ intent.getBooleanExtra(UsbManager.USB_FUNCTION_MASS_STORAGE, false));
+ notifyShareAvailabilityChange(available);
}
}
};
@@ -654,12 +659,6 @@
updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED);
}
- try {
- boolean avail = doGetShareMethodAvailable("ums");
- notifyShareAvailabilityChange("ums", avail);
- } catch (Exception ex) {
- Slog.w(TAG, "Failed to get share availability");
- }
/*
* Now that we've done our initialization, release
* the hounds!
@@ -694,13 +693,6 @@
notifyVolumeStateChange(
cooked[2], cooked[3], Integer.parseInt(cooked[7]),
Integer.parseInt(cooked[10]));
- } else if (code == VoldResponseCode.ShareAvailabilityChange) {
- // FMT: NNN Share method <method> now <available|unavailable>
- boolean avail = false;
- if (cooked[5].equals("available")) {
- avail = true;
- }
- notifyShareAvailabilityChange(cooked[3], avail);
} else if ((code == VoldResponseCode.VolumeDiskInserted) ||
(code == VoldResponseCode.VolumeDiskRemoved) ||
(code == VoldResponseCode.VolumeBadRemoval)) {
@@ -835,42 +827,6 @@
}
}
- private boolean doGetShareMethodAvailable(String method) {
- ArrayList<String> rsp;
- try {
- rsp = mConnector.doCommand("share status " + method);
- } catch (NativeDaemonConnectorException ex) {
- Slog.e(TAG, "Failed to determine whether share method " + method + " is available.");
- return false;
- }
-
- for (String line : rsp) {
- String[] tok = line.split(" ");
- if (tok.length < 3) {
- Slog.e(TAG, "Malformed response to share status " + method);
- return false;
- }
-
- int code;
- try {
- code = Integer.parseInt(tok[0]);
- } catch (NumberFormatException nfe) {
- Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
- return false;
- }
- if (code == VoldResponseCode.ShareStatusResult) {
- if (tok[2].equals("available"))
- return true;
- return false;
- } else {
- Slog.e(TAG, String.format("Unexpected response code %d", code));
- return false;
- }
- }
- Slog.e(TAG, "Got an empty response");
- return false;
- }
-
private int doMountVolume(String path) {
int rc = StorageResultCode.OperationSucceeded;
@@ -1018,13 +974,9 @@
return false;
}
- private void notifyShareAvailabilityChange(String method, final boolean avail) {
- if (!method.equals("ums")) {
- Slog.w(TAG, "Ignoring unsupported share method {" + method + "}");
- return;
- }
-
+ private void notifyShareAvailabilityChange(final boolean avail) {
synchronized (mListeners) {
+ mUmsAvailable = avail;
for (int i = mListeners.size() -1; i >= 0; i--) {
MountServiceBinderListener bl = mListeners.get(i);
try {
@@ -1189,8 +1141,13 @@
// XXX: This will go away soon in favor of IMountServiceObserver
mPms = (PackageManagerService) ServiceManager.getService("package");
- mContext.registerReceiver(mBroadcastReceiver,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ // don't bother monitoring USB if mass storage is not supported on our primary volume
+ if (mPrimaryVolume != null && mPrimaryVolume.allowMassStorage()) {
+ filter.addAction(UsbManager.ACTION_USB_STATE);
+ }
+ mContext.registerReceiver(mBroadcastReceiver, filter, null, null);
mHandlerThread = new HandlerThread("MountService");
mHandlerThread.start();
@@ -1323,7 +1280,9 @@
if (getUmsEnabling()) {
return true;
}
- return doGetShareMethodAvailable("ums");
+ synchronized (mListeners) {
+ return mUmsAvailable;
+ }
}
public void setUsbMassStorageEnabled(boolean enable) {
@@ -1419,7 +1378,7 @@
return doFormatVolume(path);
}
- public int []getStorageUsers(String path) {
+ public int[] getStorageUsers(String path) {
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
try {
@@ -1667,6 +1626,30 @@
}
}
+ public String getSecureContainerFilesystemPath(String id) {
+ validatePermission(android.Manifest.permission.ASEC_ACCESS);
+ waitForReady();
+ warnOnNotMounted();
+
+ try {
+ ArrayList<String> rsp = mConnector.doCommand(String.format("asec fspath %s", id));
+ String []tok = rsp.get(0).split(" ");
+ int code = Integer.parseInt(tok[0]);
+ if (code != VoldResponseCode.AsecPathResult) {
+ throw new IllegalStateException(String.format("Unexpected response code %d", code));
+ }
+ return tok[1];
+ } catch (NativeDaemonConnectorException e) {
+ int code = e.getCode();
+ if (code == VoldResponseCode.OpFailedStorageNotFound) {
+ Slog.i(TAG, String.format("Container '%s' not found", id));
+ return null;
+ } else {
+ throw new IllegalStateException(String.format("Unexpected response code %d", code));
+ }
+ }
+ }
+
public void finishMediaUpdate() {
mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE);
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 2190b30..adc6570 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,11 @@
package com.android.server;
+import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
+import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.INetworkManagementEventObserver;
@@ -32,16 +37,24 @@
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.concurrent.CountDownLatch;
@@ -59,8 +72,18 @@
private static final int ADD = 1;
private static final int REMOVE = 2;
- /** Base path to UID-granularity network statistics. */
- private static final File PATH_PROC_UID_STAT = new File("/proc/uid_stat");
+ /** Path to {@code /proc/uid_stat}. */
+ @Deprecated
+ private final File mProcStatsUidstat;
+ /** Path to {@code /proc/net/xt_qtaguid/stats}. */
+ private final File mProcStatsNetfilter;
+
+ /** {@link #mProcStatsNetfilter} headers. */
+ private static final String KEY_IFACE = "iface";
+ private static final String KEY_TAG_HEX = "acct_tag_hex";
+ private static final String KEY_UID = "uid_tag_int";
+ private static final String KEY_RX = "rx_bytes";
+ private static final String KEY_TX = "tx_bytes";
class NetdResponseCode {
public static final int InterfaceListResult = 110;
@@ -72,7 +95,6 @@
public static final int IpFwdStatusResult = 211;
public static final int InterfaceGetCfgResult = 213;
public static final int SoftapStatusResult = 214;
- public static final int UsbRNDISStatusResult = 215;
public static final int InterfaceRxCounterResult = 216;
public static final int InterfaceTxCounterResult = 217;
public static final int InterfaceRxThrottleResult = 218;
@@ -96,15 +118,23 @@
private ArrayList<INetworkManagementEventObserver> mObservers;
+ /** Set of interfaces with active quotas. */
+ private HashSet<String> mInterfaceQuota = Sets.newHashSet();
+ /** Set of UIDs with active reject rules. */
+ private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
+
/**
* Constructs a new NetworkManagementService instance
*
* @param context Binder context for this service
*/
- private NetworkManagementService(Context context) {
+ private NetworkManagementService(Context context, File procRoot) {
mContext = context;
mObservers = new ArrayList<INetworkManagementEventObserver>();
+ mProcStatsUidstat = new File(procRoot, "uid_stat");
+ mProcStatsNetfilter = new File(procRoot, "net/xt_qtaguid/stats");
+
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
return;
}
@@ -115,7 +145,8 @@
}
public static NetworkManagementService create(Context context) throws InterruptedException {
- NetworkManagementService service = new NetworkManagementService(context);
+ NetworkManagementService service = new NetworkManagementService(
+ context, new File("/proc/"));
if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
service.mThread.start();
if (DBG) Slog.d(TAG, "Awaiting socket connection");
@@ -124,6 +155,12 @@
return service;
}
+ // @VisibleForTesting
+ public static NetworkManagementService createForTest(Context context, File procRoot) {
+ // TODO: eventually connect with mock netd
+ return new NetworkManagementService(context, procRoot);
+ }
+
public void registerObserver(INetworkManagementEventObserver obs) {
Slog.d(TAG, "Registering observer");
mObservers.add(obs);
@@ -135,12 +172,26 @@
}
/**
- * Notify our observers of an interface link status change
+ * Notify our observers of an interface status change
*/
- private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
+ private void notifyInterfaceStatusChanged(String iface, boolean up) {
for (INetworkManagementEventObserver obs : mObservers) {
try {
- obs.interfaceLinkStatusChanged(iface, link);
+ obs.interfaceStatusChanged(iface, up);
+ } catch (Exception ex) {
+ Slog.w(TAG, "Observer notifier failed", ex);
+ }
+ }
+ }
+
+ /**
+ * Notify our observers of an interface link state change
+ * (typically, an Ethernet cable has been plugged-in or unplugged).
+ */
+ private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+ for (INetworkManagementEventObserver obs : mObservers) {
+ try {
+ obs.interfaceLinkStateChanged(iface, up);
} catch (Exception ex) {
Slog.w(TAG, "Observer notifier failed", ex);
}
@@ -201,6 +252,7 @@
* Format: "NNN Iface added <name>"
* "NNN Iface removed <name>"
* "NNN Iface changed <name> <up/down>"
+ * "NNN Iface linkstatus <name> <up/down>"
*/
if (cooked.length < 4 || !cooked[1].equals("Iface")) {
throw new IllegalStateException(
@@ -213,7 +265,10 @@
notifyInterfaceRemoved(cooked[3]);
return true;
} else if (cooked[2].equals("changed") && cooked.length == 5) {
- notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
+ notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+ return true;
+ } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+ notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
return true;
}
throw new IllegalStateException(
@@ -311,6 +366,18 @@
}
}
+ /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
+ IPv6 addresses on interface down, but we need to do full clean up here */
+ public void clearInterfaceAddresses(String iface) throws IllegalStateException {
+ String cmd = String.format("interface clearaddrs %s", iface);
+ try {
+ mConnector.doCommand(cmd);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException(
+ "Unable to communicate with native daemon to interface clearallips - " + e);
+ }
+ }
+
public void addRoute(String interfaceName, RouteInfo route) {
modifyRoute(interfaceName, ADD, route);
}
@@ -700,52 +767,6 @@
}
}
- public void startUsbRNDIS() throws IllegalStateException {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
- try {
- mConnector.doCommand("usb startrndis");
- } catch (NativeDaemonConnectorException e) {
- throw new IllegalStateException(
- "Error communicating to native daemon for starting RNDIS", e);
- }
- }
-
- public void stopUsbRNDIS() throws IllegalStateException {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
- try {
- mConnector.doCommand("usb stoprndis");
- } catch (NativeDaemonConnectorException e) {
- throw new IllegalStateException("Error communicating to native daemon", e);
- }
- }
-
- public boolean isUsbRNDISStarted() throws IllegalStateException {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
- ArrayList<String> rsp;
- try {
- rsp = mConnector.doCommand("usb rndisstatus");
- } catch (NativeDaemonConnectorException e) {
- throw new IllegalStateException(
- "Error communicating to native daemon to check RNDIS status", e);
- }
-
- for (String line : rsp) {
- String []tok = line.split(" ");
- int code = Integer.parseInt(tok[0]);
- if (code == NetdResponseCode.UsbRNDISStatusResult) {
- if (tok[3].equals("started"))
- return true;
- return false;
- } else {
- throw new IllegalStateException(String.format("Unexpected response code %d", code));
- }
- }
- throw new IllegalStateException("Got an empty response");
- }
-
public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
throws IllegalStateException {
mContext.enforceCallingOrSelfPermission(
@@ -887,7 +908,7 @@
for (String iface : ifaces) {
final long rx = getInterfaceCounter(iface, true);
final long tx = getInterfaceCounter(iface, false);
- stats.addEntry(iface, NetworkStats.UID_ALL, rx, tx);
+ stats.addEntry(iface, UID_ALL, TAG_NONE, rx, tx);
}
return stats;
@@ -898,38 +919,177 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
- final String[] knownUids = PATH_PROC_UID_STAT.list();
- final NetworkStats stats = new NetworkStats(
- SystemClock.elapsedRealtime(), knownUids.length);
-
- for (String uid : knownUids) {
- final int uidInt = Integer.parseInt(uid);
- collectNetworkStatsDetail(stats, uidInt);
+ if (mProcStatsNetfilter.exists()) {
+ return getNetworkStatsDetailNetfilter(UID_ALL);
+ } else {
+ return getNetworkStatsDetailUidstat(UID_ALL);
}
-
- return stats;
}
@Override
+ public void setInterfaceQuota(String iface, long quota) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mInterfaceQuota) {
+ if (mInterfaceQuota.contains(iface)) {
+ // TODO: eventually consider throwing
+ return;
+ }
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth setiquota ").append(iface).append(" ").append(quota);
+
+ try {
+ // TODO: add support for quota shared across interfaces
+ mConnector.doCommand(command.toString());
+ mInterfaceQuota.add(iface);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+ }
+ }
+
+ @Override
+ public void removeInterfaceQuota(String iface) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mInterfaceQuota) {
+ if (!mInterfaceQuota.contains(iface)) {
+ // TODO: eventually consider throwing
+ return;
+ }
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth removeiquota ").append(iface);
+
+ try {
+ // TODO: add support for quota shared across interfaces
+ mConnector.doCommand(command.toString());
+ mInterfaceQuota.remove(iface);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+ }
+ }
+
+ @Override
+ public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mUidRejectOnQuota) {
+ final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
+ if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
+ // TODO: eventually consider throwing
+ return;
+ }
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth");
+ if (rejectOnQuotaInterfaces) {
+ command.append(" addnaughtyapps");
+ } else {
+ command.append(" removenaughtyapps");
+ }
+ command.append(" ").append(uid);
+
+ try {
+ mConnector.doCommand(command.toString());
+ if (rejectOnQuotaInterfaces) {
+ mUidRejectOnQuota.put(uid, true);
+ } else {
+ mUidRejectOnQuota.delete(uid);
+ }
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+ }
+ }
+
public NetworkStats getNetworkStatsUidDetail(int uid) {
if (Binder.getCallingUid() != uid) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
}
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- collectNetworkStatsDetail(stats, uid);
+ if (mProcStatsNetfilter.exists()) {
+ return getNetworkStatsDetailNetfilter(uid);
+ } else {
+ return getNetworkStatsDetailUidstat(uid);
+ }
+ }
+
+ /**
+ * Build {@link NetworkStats} with detailed UID statistics.
+ */
+ private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+ final ArrayList<String> keys = Lists.newArrayList();
+ final ArrayList<String> values = Lists.newArrayList();
+ final HashMap<String, String> parsed = Maps.newHashMap();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mProcStatsNetfilter));
+
+ // parse first line as header
+ String line = reader.readLine();
+ splitLine(line, keys);
+
+ // parse remaining lines
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+ parseLine(keys, values, parsed);
+
+ try {
+ final String iface = parsed.get(KEY_IFACE);
+ final int tag = NetworkManagementSocketTagger.kernelToTag(
+ parsed.get(KEY_TAG_HEX));
+ final int uid = Integer.parseInt(parsed.get(KEY_UID));
+ final long rx = Long.parseLong(parsed.get(KEY_RX));
+ final long tx = Long.parseLong(parsed.get(KEY_TX));
+
+ if (limitUid == UID_ALL || limitUid == uid) {
+ stats.addEntry(iface, uid, tag, rx, tx);
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
+ }
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+
return stats;
}
- private void collectNetworkStatsDetail(NetworkStats stats, int uid) {
- // TODO: kernel module will provide interface-level stats in future
- // TODO: migrate these stats to come across netd in bulk, instead of all
- // these individual file reads.
- final File uidPath = new File(PATH_PROC_UID_STAT, Integer.toString(uid));
- final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
- final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
- stats.addEntry(NetworkStats.IFACE_ALL, uid, rx, tx);
+ /**
+ * Build {@link NetworkStats} with detailed UID statistics.
+ *
+ * @deprecated since this uses older "uid_stat" data, and doesn't provide
+ * tag-level granularity or additional variables.
+ */
+ @Deprecated
+ private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
+ final String[] knownUids;
+ if (limitUid == UID_ALL) {
+ knownUids = mProcStatsUidstat.list();
+ } else {
+ knownUids = new String[] { String.valueOf(limitUid) };
+ }
+
+ final NetworkStats stats = new NetworkStats(
+ SystemClock.elapsedRealtime(), knownUids.length);
+ for (String uid : knownUids) {
+ final int uidInt = Integer.parseInt(uid);
+ final File uidPath = new File(mProcStatsUidstat, uid);
+ final long rx = readSingleLongFromFile(new File(uidPath, "tcp_rcv"));
+ final long tx = readSingleLongFromFile(new File(uidPath, "tcp_snd"));
+ stats.addEntry(IFACE_ALL, uidInt, TAG_NONE, rx, tx);
+ }
+
+ return stats;
}
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
@@ -991,6 +1151,38 @@
return getInterfaceThrottle(iface, false);
}
+ @Override
+ public void setBandwidthControlEnabled(boolean enabled) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ mConnector.doCommand(String.format("bandwidth %s", (enabled ? "enable" : "disable")));
+ }
+
+ /**
+ * Split given line into {@link ArrayList}.
+ */
+ private static void splitLine(String line, ArrayList<String> outSplit) {
+ outSplit.clear();
+
+ final StringTokenizer t = new StringTokenizer(line);
+ while (t.hasMoreTokens()) {
+ outSplit.add(t.nextToken());
+ }
+ }
+
+ /**
+ * Zip the two given {@link ArrayList} as key and value pairs into
+ * {@link HashMap}.
+ */
+ private static void parseLine(
+ ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
+ outParsed.clear();
+
+ final int size = Math.min(keys.size(), values.size());
+ for (int i = 0; i < size; i++) {
+ outParsed.put(keys.get(i), values.get(i));
+ }
+ }
+
/**
* Utility method to read a single plain-text {@link Long} from the given
* {@link File}, usually from a {@code /proc/} filesystem.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2769004..dbfd145 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -209,9 +209,11 @@
bluetoothA2dp);
bluetooth.initAfterA2dpRegistration();
+ int airplaneModeOn = Settings.System.getInt(mContentResolver,
+ Settings.System.AIRPLANE_MODE_ON, 0);
int bluetoothOn = Settings.Secure.getInt(mContentResolver,
Settings.Secure.BLUETOOTH_ON, 0);
- if (bluetoothOn > 0) {
+ if (airplaneModeOn == 0 && bluetoothOn != 0) {
bluetooth.enable();
}
}
@@ -281,7 +283,8 @@
try {
Slog.i(TAG, "NetworkPolicy Service");
networkPolicy = new NetworkPolicyManagerService(
- context, ActivityManagerService.self(), power, networkStats);
+ context, ActivityManagerService.self(), power,
+ networkStats, networkManagement);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting NetworkPolicy Service", e);
@@ -406,8 +409,8 @@
}
try {
- Slog.i(TAG, "USB Observer");
- // Listen for USB changes
+ Slog.i(TAG, "USB Service");
+ // Manage USB host and device support
usb = new UsbService(context);
ServiceManager.addService(Context.USB_SERVICE, usb);
} catch (Throwable e) {
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 510ff62..d81dfdb 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -179,14 +179,17 @@
mIface = iface;
}
- public void interfaceLinkStatusChanged(String iface, boolean link) {
- if (link) {
+ public void interfaceStatusChanged(String iface, boolean up) {
+ if (up) {
if (TextUtils.equals(iface, mIface)) {
mHandler.obtainMessage(mMsg).sendToTarget();
}
}
}
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ }
+
public void interfaceAdded(String iface) {
// TODO - an interface added in the UP state should also trigger a StatusChanged
// notification..
@@ -533,7 +536,8 @@
long incWrite = 0;
try {
final NetworkStats stats = mNMService.getNetworkStatsSummary();
- final int index = stats.findIndex(mIface, NetworkStats.UID_ALL);
+ final int index = stats.findIndex(
+ mIface, NetworkStats.UID_ALL, NetworkStats.TAG_NONE);
if (index != -1) {
incRead = stats.rx[index] - mLastRead;
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index cb55451..7725891 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -342,6 +342,7 @@
* Protected by mWifiStateTracker lock.
*/
private final WorkSource mTmpWorkSource = new WorkSource();
+ private WifiWatchdogService mWifiWatchdogService;
WifiService(Context context) {
mContext = context;
@@ -431,6 +432,9 @@
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
setWifiEnabled(wifiEnabled);
+
+ //TODO: as part of WWS refactor, create only when needed
+ mWifiWatchdogService = new WifiWatchdogService(mContext);
}
private boolean testAndClearWifiSavedState() {
@@ -1155,6 +1159,10 @@
pw.println();
pw.println("Locks held:");
mLocks.dump(pw);
+
+ pw.println();
+ pw.println("WifiWatchdogService dump");
+ mWifiWatchdogService.dump(pw);
}
private class WifiLock extends DeathRecipient {
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index 56bfbe0..1356e2a 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -23,1428 +23,746 @@
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
-import android.net.LinkProperties;
import android.net.NetworkInfo;
+import android.net.Uri;
import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.SystemClock;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
import java.io.BufferedInputStream;
-import java.io.InputStream;
import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
+import java.io.InputStream;
+import java.io.PrintWriter;
import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
import java.net.URL;
-import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
-import java.util.Random;
import java.util.Scanner;
/**
* {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi
* network with multiple access points. After the framework successfully
- * connects to an access point, the watchdog verifies whether the DNS server is
- * reachable. If not, the watchdog blacklists the current access point, leading
- * to a connection on another access point within the same network.
+ * connects to an access point, the watchdog verifies connectivity by 'pinging'
+ * the configured DNS server using {@link DnsPinger}.
* <p>
- * The watchdog has a few safeguards:
- * <ul>
- * <li>Only monitor networks with multiple access points
- * <li>Only check at most {@link #getMaxApChecks()} different access points
- * within the network before giving up
+ * On DNS check failure, the BSSID is blacklisted if it is reasonably likely
+ * that another AP might have internet access; otherwise the SSID is disabled.
* <p>
- * The watchdog checks for connectivity on an access point by ICMP pinging the
- * DNS. There are settings that allow disabling the watchdog, or tweaking the
- * acceptable packet loss (and other various parameters).
- * <p>
- * The core logic of the watchdog is done on the main watchdog thread. Wi-Fi
- * callbacks can come in on other threads, so we must queue messages to the main
- * watchdog thread's handler. Most (if not all) state is only written to from
- * the main thread.
+ * On DNS success, the WatchdogService initiates a walled garden check via an
+ * http get. A browser windows is activated if a walled garden is detected.
*
- * {@hide}
+ * @hide
*/
public class WifiWatchdogService {
- private static final String TAG = "WifiWatchdogService";
- private static final boolean V = false;
- private static final boolean D = true;
+
+ private static final String WWS_TAG = "WifiWatchdogService";
+
+ private static final boolean VDBG = true;
+ private static final boolean DBG = true;
+
+ // Used for verbose logging
+ private String mDNSCheckLogStr;
private Context mContext;
private ContentResolver mContentResolver;
private WifiManager mWifiManager;
- private ConnectivityManager mConnectivityManager;
- /**
- * The main watchdog thread.
- */
- private WifiWatchdogThread mThread;
- /**
- * The handler for the main watchdog thread.
- */
private WifiWatchdogHandler mHandler;
- private ContentObserver mContentObserver;
+ private DnsPinger mDnsPinger;
+
+ private IntentFilter mIntentFilter;
+ private BroadcastReceiver mBroadcastReceiver;
+ private boolean mBroadcastsEnabled;
+
+ private static final int WIFI_SIGNAL_LEVELS = 4;
/**
- * The current watchdog state. Only written from the main thread!
+ * Low signal is defined as less than or equal to cut off
*/
- private WatchdogState mState = WatchdogState.IDLE;
- /**
- * The SSID of the network that the watchdog is currently monitoring. Only
- * touched in the main thread!
- */
- private String mSsid;
- /**
- * The number of access points in the current network ({@link #mSsid}) that
- * have been checked. Only touched in the main thread, using getter/setter methods.
- */
- private int mBssidCheckCount;
- /** Whether the current AP check should be canceled. */
- private boolean mShouldCancel;
+ private static final int LOW_SIGNAL_CUTOFF = 0;
+
+ private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL = 2 * 60 * 1000;
+ private static final long MIN_SINGLE_DNS_CHECK_INTERVAL = 10 * 60 * 1000;
+ private static final long MIN_WALLED_GARDEN_INTERVAL = 15 * 60 * 1000;
+
+ private static final int MAX_CHECKS_PER_SSID = 9;
+ private static final int NUM_DNS_PINGS = 7;
+ private static double MIN_RESPONSE_RATE = 0.50;
+
+ // TODO : Adjust multiple DNS downward to 250 on repeated failure
+ // private static final int MULTI_DNS_PING_TIMEOUT_MS = 250;
+
+ private static final int DNS_PING_TIMEOUT_MS = 800;
+ private static final long DNS_PING_INTERVAL = 250;
+
+ private static final long BLACKLIST_FOLLOWUP_INTERVAL = 15 * 1000;
+
+ private Status mStatus = new Status();
+
+ private static class Status {
+ String bssid = "";
+ String ssid = "";
+
+ HashSet<String> allBssids = new HashSet<String>();
+ int numFullDNSchecks = 0;
+
+ long lastSingleCheckTime = -24 * 60 * 60 * 1000;
+ long lastWalledGardenCheckTime = -24 * 60 * 60 * 1000;
+
+ WatchdogState state = WatchdogState.INACTIVE;
+
+ // Info for dns check
+ int dnsCheckTries = 0;
+ int dnsCheckSuccesses = 0;
+
+ public int signal = -200;
+
+ }
+
+ private enum WatchdogState {
+ /**
+ * Full DNS check in progress
+ */
+ DNS_FULL_CHECK,
+
+ /**
+ * Walled Garden detected, will pop up browser next round.
+ */
+ WALLED_GARDEN_DETECTED,
+
+ /**
+ * DNS failed, will blacklist/disable AP next round
+ */
+ DNS_CHECK_FAILURE,
+
+ /**
+ * Online or displaying walled garden auth page
+ */
+ CHECKS_COMPLETE,
+
+ /**
+ * Watchdog idle, network has been blacklisted or received disconnect
+ * msg
+ */
+ INACTIVE,
+
+ BLACKLISTED_AP
+ }
WifiWatchdogService(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- createThread();
-
- // The content observer to listen needs a handler, which createThread creates
+ mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context,
+ ConnectivityManager.TYPE_WIFI);
+
+ HandlerThread handlerThread = new HandlerThread("WifiWatchdogServiceThread");
+ handlerThread.start();
+ mHandler = new WifiWatchdogHandler(handlerThread.getLooper());
+
+ setupNetworkReceiver();
+
+ // The content observer to listen needs a handler, which createThread
+ // creates
registerForSettingsChanges();
+
+ // Start things off
if (isWatchdogEnabled()) {
- registerForWifiBroadcasts();
+ mHandler.sendEmptyMessage(WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT);
}
-
- if (V) {
- myLogV("WifiWatchdogService: Created");
- }
+ }
+
+ /**
+ *
+ */
+ private void setupNetworkReceiver() {
+ mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ mHandler.sendMessage(mHandler.obtainMessage(
+ WifiWatchdogHandler.MESSAGE_NETWORK_EVENT,
+ intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)
+ ));
+ } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+ mHandler.sendEmptyMessage(WifiWatchdogHandler.RSSI_CHANGE_EVENT);
+ } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+ mHandler.sendEmptyMessage(WifiWatchdogHandler.SCAN_RESULTS_AVAILABLE);
+ } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ mHandler.sendMessage(mHandler.obtainMessage(
+ WifiWatchdogHandler.WIFI_STATE_CHANGE,
+ intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 4)));
+ }
+ }
+ };
+
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+ mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
}
/**
* Observes the watchdog on/off setting, and takes action when changed.
*/
private void registerForSettingsChanges() {
- ContentResolver contentResolver = mContext.getContentResolver();
- contentResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), false,
- mContentObserver = new ContentObserver(mHandler) {
+ ContentObserver contentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- if (isWatchdogEnabled()) {
- registerForWifiBroadcasts();
- } else {
- unregisterForWifiBroadcasts();
- if (mHandler != null) {
- mHandler.disableWatchdog();
+ mHandler.sendEmptyMessage((WifiWatchdogHandler.MESSAGE_CONTEXT_EVENT));
+ }
+ };
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON),
+ false, contentObserver);
+ }
+
+ private void handleNewConnection() {
+ WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ String newSsid = wifiInfo.getSSID();
+ String newBssid = wifiInfo.getBSSID();
+
+ if (VDBG) {
+ Slog.v(WWS_TAG, String.format("handleConnected:: old (%s, %s) ==> new (%s, %s)",
+ mStatus.ssid, mStatus.bssid, newSsid, newBssid));
+ }
+
+ if (TextUtils.isEmpty(newSsid) || TextUtils.isEmpty(newBssid)) {
+ return;
+ }
+
+ if (!TextUtils.equals(mStatus.ssid, newSsid)) {
+ mStatus = new Status();
+ mStatus.ssid = newSsid;
+ }
+
+ mStatus.bssid = newBssid;
+ mStatus.allBssids.add(newBssid);
+ mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+
+ initDnsFullCheck();
+ }
+
+ public void updateRssi() {
+ WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ if (!TextUtils.equals(mStatus.ssid, wifiInfo.getSSID()) ||
+ !TextUtils.equals(mStatus.bssid, wifiInfo.getBSSID())) {
+ return;
+ }
+
+ mStatus.signal = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), WIFI_SIGNAL_LEVELS);
+ }
+
+ /**
+ * Single step in state machine
+ */
+ private void handleStateStep() {
+ // Slog.v(WWS_TAG, "handleStateStep:: " + mStatus.state);
+
+ switch (mStatus.state) {
+ case DNS_FULL_CHECK:
+ if (VDBG) {
+ Slog.v(WWS_TAG, "DNS_FULL_CHECK: " + mDNSCheckLogStr);
+ }
+
+ long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+ DNS_PING_TIMEOUT_MS);
+
+ mStatus.dnsCheckTries++;
+ if (pingResponseTime >= 0)
+ mStatus.dnsCheckSuccesses++;
+
+ if (DBG) {
+ if (pingResponseTime >= 0) {
+ mDNSCheckLogStr += " | " + pingResponseTime;
+ } else {
+ mDNSCheckLogStr += " | " + "x";
}
}
+
+ switch (currentDnsCheckStatus()) {
+ case SUCCESS:
+ if (DBG) {
+ Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Success");
+ }
+ doWalledGardenCheck();
+ break;
+ case FAILURE:
+ if (DBG) {
+ Slog.d(WWS_TAG, mDNSCheckLogStr + " -- Failure");
+ }
+ mStatus.state = WatchdogState.DNS_CHECK_FAILURE;
+ break;
+ case INCOMPLETE:
+ // Taking no action
+ break;
+ }
+ break;
+ case DNS_CHECK_FAILURE:
+ WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ if (!mStatus.ssid.equals(wifiInfo.getSSID()) ||
+ !mStatus.bssid.equals(wifiInfo.getBSSID())) {
+ Slog.i(WWS_TAG, "handleState DNS_CHECK_FAILURE:: network has changed!");
+ mStatus.state = WatchdogState.INACTIVE;
+ break;
+ }
+
+ if (mStatus.numFullDNSchecks >= mStatus.allBssids.size() ||
+ mStatus.numFullDNSchecks >= MAX_CHECKS_PER_SSID) {
+ disableAP(wifiInfo);
+ } else {
+ blacklistAP();
+ }
+ break;
+ case WALLED_GARDEN_DETECTED:
+ popUpBrowser();
+ mStatus.state = WatchdogState.CHECKS_COMPLETE;
+ break;
+ case BLACKLISTED_AP:
+ WifiInfo wifiInfo2 = mWifiManager.getConnectionInfo();
+ if (wifiInfo2.getSupplicantState() != SupplicantState.COMPLETED) {
+ Slog.d(WWS_TAG,
+ "handleState::BlacklistedAP - offline, but didn't get disconnect!");
+ mStatus.state = WatchdogState.INACTIVE;
+ break;
+ }
+ if (mStatus.bssid.equals(wifiInfo2.getBSSID())) {
+ Slog.d(WWS_TAG, "handleState::BlacklistedAP - connected to same bssid");
+ if (!handleSingleDnsCheck()) {
+ disableAP(wifiInfo2);
+ break;
+ }
+ }
+
+ Slog.d(WWS_TAG, "handleState::BlacklistedAP - Simiulating a new connection");
+ handleNewConnection();
+ break;
+ }
+ }
+
+ private void doWalledGardenCheck() {
+ if (!isWalledGardenTestEnabled()) {
+ if (VDBG)
+ Slog.v(WWS_TAG, "Skipping walled garden check - disabled");
+ mStatus.state = WatchdogState.CHECKS_COMPLETE;
+ return;
+ }
+ long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL,
+ mStatus.lastWalledGardenCheckTime);
+ if (waitTime > 0) {
+ if (VDBG) {
+ Slog.v(WWS_TAG, "Skipping walled garden check - wait " +
+ waitTime + " ms.");
}
- });
+ mStatus.state = WatchdogState.CHECKS_COMPLETE;
+ return;
+ }
+
+ mStatus.lastWalledGardenCheckTime = SystemClock.elapsedRealtime();
+ if (isWalledGardenConnection()) {
+ if (DBG)
+ Slog.d(WWS_TAG,
+ "Walled garden test complete - walled garden detected");
+ mStatus.state = WatchdogState.WALLED_GARDEN_DETECTED;
+ } else {
+ if (DBG)
+ Slog.d(WWS_TAG, "Walled garden test complete - online");
+ mStatus.state = WatchdogState.CHECKS_COMPLETE;
+ }
+ }
+
+ private boolean handleSingleDnsCheck() {
+ mStatus.lastSingleCheckTime = SystemClock.elapsedRealtime();
+ long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(),
+ DNS_PING_TIMEOUT_MS);
+ if (DBG) {
+ Slog.d(WWS_TAG, "Ran a single DNS ping. Response time: " + responseTime);
+ }
+ if (responseTime < 0) {
+ return false;
+ }
+ return true;
+
+ }
+
+ /**
+ * @return Delay in MS before next single DNS check can proceed.
+ */
+ private long timeToNextScheduledDNSCheck() {
+ if (mStatus.signal > LOW_SIGNAL_CUTOFF) {
+ return waitTime(MIN_SINGLE_DNS_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+ } else {
+ return waitTime(MIN_LOW_SIGNAL_CHECK_INTERVAL, mStatus.lastSingleCheckTime);
+ }
+ }
+
+ /**
+ * Helper to return wait time left given a min interval and last run
+ *
+ * @param interval minimum wait interval
+ * @param lastTime last time action was performed in
+ * SystemClock.elapsedRealtime()
+ * @return non negative time to wait
+ */
+ private static long waitTime(long interval, long lastTime) {
+ long wait = interval + lastTime - SystemClock.elapsedRealtime();
+ return wait > 0 ? wait : 0;
+ }
+
+ private void popUpBrowser() {
+ Uri uri = Uri.parse("http://www.google.com");
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
+ Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ }
+
+ private void disableAP(WifiInfo info) {
+ // TODO : Unban networks if they had low signal ?
+ Slog.i(WWS_TAG, String.format("Disabling current SSID, %s [bssid %s]. " +
+ "numChecks %d, numAPs %d", mStatus.ssid, mStatus.bssid,
+ mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+ mWifiManager.disableNetwork(info.getNetworkId());
+ mStatus.state = WatchdogState.INACTIVE;
+ }
+
+ private void blacklistAP() {
+ Slog.i(WWS_TAG, String.format("Blacklisting current BSSID %s [ssid %s]. " +
+ "numChecks %d, numAPs %d", mStatus.bssid, mStatus.ssid,
+ mStatus.numFullDNSchecks, mStatus.allBssids.size()));
+
+ mWifiManager.addToBlacklist(mStatus.bssid);
+ mWifiManager.reassociate();
+ mStatus.state = WatchdogState.BLACKLISTED_AP;
+ }
+
+ /**
+ * Checks the scan for new BBIDs using current mSsid
+ */
+ private void updateBssids() {
+ String curSsid = mStatus.ssid;
+ HashSet<String> bssids = mStatus.allBssids;
+ List<ScanResult> results = mWifiManager.getScanResults();
+ int oldNumBssids = bssids.size();
+
+ if (results == null) {
+ if (VDBG) {
+ Slog.v(WWS_TAG, "updateBssids: Got null scan results!");
+ }
+ return;
+ }
+
+ for (ScanResult result : results) {
+ if (result != null && curSsid.equals(result.SSID))
+ bssids.add(result.BSSID);
+ }
+
+ // if (VDBG && bssids.size() - oldNumBssids > 0) {
+ // Slog.v(WWS_TAG,
+ // String.format("updateBssids:: Found %d new APs (total %d) on SSID %s",
+ // bssids.size() - oldNumBssids, bssids.size(), curSsid));
+ // }
+ }
+
+ enum DnsCheckStatus {
+ SUCCESS,
+ FAILURE,
+ INCOMPLETE
+ }
+
+ /**
+ * Computes the current results of the dns check, ends early if outcome is
+ * assured.
+ */
+ private DnsCheckStatus currentDnsCheckStatus() {
+ /**
+ * After a full ping count, if we have more responses than this cutoff,
+ * the outcome is success; else it is 'failure'.
+ */
+ double pingResponseCutoff = MIN_RESPONSE_RATE * NUM_DNS_PINGS;
+ int remainingChecks = NUM_DNS_PINGS - mStatus.dnsCheckTries;
+
+ /**
+ * Our final success count will be at least this big, so we're
+ * guaranteed to succeed.
+ */
+ if (mStatus.dnsCheckSuccesses >= pingResponseCutoff) {
+ return DnsCheckStatus.SUCCESS;
+ }
+
+ /**
+ * Our final count will be at most the current count plus the remaining
+ * pings - we're guaranteed to fail.
+ */
+ if (remainingChecks + mStatus.dnsCheckSuccesses < pingResponseCutoff) {
+ return DnsCheckStatus.FAILURE;
+ }
+
+ return DnsCheckStatus.INCOMPLETE;
+ }
+
+ private void initDnsFullCheck() {
+ if (DBG) {
+ Slog.d(WWS_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime());
+ }
+ mStatus.numFullDNSchecks++;
+ mStatus.dnsCheckSuccesses = 0;
+ mStatus.dnsCheckTries = 0;
+ mStatus.state = WatchdogState.DNS_FULL_CHECK;
+
+ if (DBG) {
+ mDNSCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ",
+ mStatus.numFullDNSchecks, mDnsPinger.getDns(),
+ mStatus.ssid);
+ }
+ }
+
+ /**
+ * DNS based detection techniques do not work at all hotspots. The one sure
+ * way to check a walled garden is to see if a URL fetch on a known address
+ * fetches the data we expect
+ */
+ private boolean isWalledGardenConnection() {
+ InputStream in = null;
+ HttpURLConnection urlConnection = null;
+ try {
+ URL url = new URL(getWalledGardenUrl());
+ urlConnection = (HttpURLConnection) url.openConnection();
+ in = new BufferedInputStream(urlConnection.getInputStream());
+ Scanner scanner = new Scanner(in);
+ if (scanner.findInLine(getWalledGardenPattern()) != null) {
+ return false;
+ } else {
+ return true;
+ }
+ } catch (IOException e) {
+ return false;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ if (urlConnection != null)
+ urlConnection.disconnect();
+ }
+ }
+
+ /**
+ * There is little logic inside this class, instead methods of the form
+ * "handle___" are called in the main {@link WifiWatchdogService}.
+ */
+ private class WifiWatchdogHandler extends Handler {
+ /**
+ * Major network event, object is NetworkInfo
+ */
+ static final int MESSAGE_NETWORK_EVENT = 1;
+ /**
+ * Change in settings, no object
+ */
+ static final int MESSAGE_CONTEXT_EVENT = 2;
+
+ /**
+ * Change in signal strength
+ */
+ static final int RSSI_CHANGE_EVENT = 3;
+ static final int SCAN_RESULTS_AVAILABLE = 4;
+
+ static final int WIFI_STATE_CHANGE = 5;
+
+ /**
+ * Single step of state machine. One DNS check, or one WalledGarden
+ * check, or one external action. We separate out external actions to
+ * increase chance of detecting that a check failure is caused by change
+ * in network status. Messages should have an arg1 which to sync status
+ * messages.
+ */
+ static final int CHECK_SEQUENCE_STEP = 10;
+ static final int SINGLE_DNS_CHECK = 11;
+
+ /**
+ * @param looper
+ */
+ public WifiWatchdogHandler(Looper looper) {
+ super(looper);
+ }
+
+ boolean singleCheckQueued = false;
+ long queuedSingleDnsCheckArrival;
+
+ /**
+ * Sends a singleDnsCheck message with shortest time - guards against
+ * multiple.
+ */
+ private boolean queueSingleDnsCheck() {
+ long delay = timeToNextScheduledDNSCheck();
+ long newArrival = delay + SystemClock.elapsedRealtime();
+ if (singleCheckQueued && queuedSingleDnsCheckArrival <= newArrival)
+ return true;
+ queuedSingleDnsCheckArrival = newArrival;
+ singleCheckQueued = true;
+ removeMessages(SINGLE_DNS_CHECK);
+ return sendMessageDelayed(obtainMessage(SINGLE_DNS_CHECK), delay);
+ }
+
+ boolean checkSequenceQueued = false;
+ long queuedCheckSequenceArrival;
+
+ /**
+ * Sends a state_machine_step message if the delay requested is lower
+ * than the current delay.
+ */
+ private boolean sendCheckSequenceStep(long delay) {
+ long newArrival = delay + SystemClock.elapsedRealtime();
+ if (checkSequenceQueued && queuedCheckSequenceArrival <= newArrival)
+ return true;
+ queuedCheckSequenceArrival = newArrival;
+ checkSequenceQueued = true;
+ removeMessages(CHECK_SEQUENCE_STEP);
+ return sendMessageDelayed(obtainMessage(CHECK_SEQUENCE_STEP), delay);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case CHECK_SEQUENCE_STEP:
+ checkSequenceQueued = false;
+ handleStateStep();
+ if (mStatus.state == WatchdogState.CHECKS_COMPLETE) {
+ queueSingleDnsCheck();
+ } else if (mStatus.state == WatchdogState.DNS_FULL_CHECK) {
+ sendCheckSequenceStep(DNS_PING_INTERVAL);
+ } else if (mStatus.state == WatchdogState.BLACKLISTED_AP) {
+ sendCheckSequenceStep(BLACKLIST_FOLLOWUP_INTERVAL);
+ } else if (mStatus.state != WatchdogState.INACTIVE) {
+ sendCheckSequenceStep(0);
+ }
+ return;
+ case MESSAGE_NETWORK_EVENT:
+ if (!mBroadcastsEnabled) {
+ Slog.e(WWS_TAG,
+ "MessageNetworkEvent - WatchdogService not enabled... returning");
+ return;
+ }
+ NetworkInfo info = (NetworkInfo) msg.obj;
+ switch (info.getState()) {
+ case DISCONNECTED:
+ mStatus.state = WatchdogState.INACTIVE;
+ return;
+ case CONNECTED:
+ handleNewConnection();
+ sendCheckSequenceStep(0);
+ }
+ return;
+ case SINGLE_DNS_CHECK:
+ singleCheckQueued = false;
+ if (mStatus.state != WatchdogState.CHECKS_COMPLETE) {
+ Slog.d(WWS_TAG, "Single check returning, curState: " + mStatus.state);
+ break;
+ }
+
+ if (!handleSingleDnsCheck()) {
+ initDnsFullCheck();
+ sendCheckSequenceStep(0);
+ } else {
+ queueSingleDnsCheck();
+ }
+
+ break;
+ case RSSI_CHANGE_EVENT:
+ updateRssi();
+ if (mStatus.state == WatchdogState.CHECKS_COMPLETE)
+ queueSingleDnsCheck();
+ break;
+ case SCAN_RESULTS_AVAILABLE:
+ updateBssids();
+ break;
+ case WIFI_STATE_CHANGE:
+ if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) {
+ Slog.i(WWS_TAG, "WifiStateDisabling -- Resetting WatchdogState");
+ mStatus = new Status();
+ }
+ break;
+ case MESSAGE_CONTEXT_EVENT:
+ if (isWatchdogEnabled() && !mBroadcastsEnabled) {
+ mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
+ mBroadcastsEnabled = true;
+ Slog.i(WWS_TAG, "WifiWatchdogService enabled");
+ } else if (!isWatchdogEnabled() && mBroadcastsEnabled) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ removeMessages(SINGLE_DNS_CHECK);
+ removeMessages(CHECK_SEQUENCE_STEP);
+ mBroadcastsEnabled = false;
+ Slog.i(WWS_TAG, "WifiWatchdogService disabled");
+ }
+ break;
+ }
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.print("WatchdogStatus: ");
+ pw.print("State " + mStatus.state);
+ pw.println(", network [" + mStatus.ssid + ", " + mStatus.bssid + "]");
+ pw.print("checkCount " + mStatus.numFullDNSchecks);
+ pw.println(", bssids: " + mStatus.allBssids);
+ pw.print(", hasCheckMessages? " +
+ mHandler.hasMessages(WifiWatchdogHandler.CHECK_SEQUENCE_STEP));
+ pw.println(" hasSingleCheckMessages? " +
+ mHandler.hasMessages(WifiWatchdogHandler.SINGLE_DNS_CHECK));
+ pw.println("DNS check log str: " + mDNSCheckLogStr);
+ pw.println("lastSingleCheck: " + mStatus.lastSingleCheckTime);
+ }
+
+ /**
+ * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
+ */
+ private Boolean isWalledGardenTestEnabled() {
+ return Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
+ }
+
+ /**
+ * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
+ */
+ private String getWalledGardenUrl() {
+ String url = Settings.Secure.getString(mContentResolver,
+ Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
+ if (TextUtils.isEmpty(url))
+ return "http://www.google.com/";
+ return url;
+ }
+
+ /**
+ * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
+ */
+ private String getWalledGardenPattern() {
+ String pattern = Settings.Secure.getString(mContentResolver,
+ Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
+ if (TextUtils.isEmpty(pattern))
+ return "<title>.*Google.*</title>";
+ return pattern;
}
/**
* @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON
*/
private boolean isWatchdogEnabled() {
- return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_AP_COUNT
- */
- private int getApCount() {
return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_AP_COUNT, 2);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT
- */
- private int getInitialIgnoredPingCount() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT , 2);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_COUNT
- */
- private int getPingCount() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_PING_COUNT, 4);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_TIMEOUT_MS
- */
- private int getPingTimeoutMs() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS, 500);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_PING_DELAY_MS
- */
- private int getPingDelayMs() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS, 250);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED
- */
- private Boolean isWalledGardenTestEnabled() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1;
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL
- */
- private String getWalledGardenUrl() {
- String url = Settings.Secure.getString(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL);
- if (TextUtils.isEmpty(url)) return "http://www.google.com/";
- return url;
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN
- */
- private String getWalledGardenPattern() {
- String pattern = Settings.Secure.getString(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN);
- if (TextUtils.isEmpty(pattern)) return "<title>.*Google.*</title>";
- return pattern;
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE
- */
- private int getAcceptablePacketLossPercentage() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE, 25);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS
- */
- private int getMaxApChecks() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS, 7);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED
- */
- private boolean isBackgroundCheckEnabled() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED, 1) == 1;
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS
- */
- private int getBackgroundCheckDelayMs() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS, 60000);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS
- */
- private int getBackgroundCheckTimeoutMs() {
- return Settings.Secure.getInt(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, 1000);
- }
-
- /**
- * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WATCH_LIST
- * @return the comma-separated list of SSIDs
- */
- private String getWatchList() {
- return Settings.Secure.getString(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_WATCH_LIST);
- }
-
- /**
- * Registers to receive the necessary Wi-Fi broadcasts.
- */
- private void registerForWifiBroadcasts() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- mContext.registerReceiver(mReceiver, intentFilter);
- }
-
- /**
- * Unregisters from receiving the Wi-Fi broadcasts.
- */
- private void unregisterForWifiBroadcasts() {
- mContext.unregisterReceiver(mReceiver);
- }
-
- /**
- * Creates the main watchdog thread, including waiting for the handler to be
- * created.
- */
- private void createThread() {
- mThread = new WifiWatchdogThread();
- mThread.start();
- waitForHandlerCreation();
- }
-
- /**
- * Unregister broadcasts and quit the watchdog thread
- */
- //TODO: Change back to running WWS when needed
-// private void quit() {
-// unregisterForWifiBroadcasts();
-// mContext.getContentResolver().unregisterContentObserver(mContentObserver);
-// mHandler.removeAllActions();
-// mHandler.getLooper().quit();
-// }
-
- /**
- * Waits for the main watchdog thread to create the handler.
- */
- private void waitForHandlerCreation() {
- synchronized(this) {
- while (mHandler == null) {
- try {
- // Wait for the handler to be set by the other thread
- wait();
- } catch (InterruptedException e) {
- Slog.e(TAG, "Interrupted while waiting on handler.");
- }
- }
- }
- }
-
- // Utility methods
-
- /**
- * Logs with the current thread.
- */
- private static void myLogV(String message) {
- Slog.v(TAG, "(" + Thread.currentThread().getName() + ") " + message);
- }
-
- private static void myLogD(String message) {
- Slog.d(TAG, "(" + Thread.currentThread().getName() + ") " + message);
- }
-
- /**
- * Gets the first DNS of the current AP.
- *
- * @return The first DNS of the current AP.
- */
- private InetAddress getDns() {
- if (mConnectivityManager == null) {
- mConnectivityManager = (ConnectivityManager)mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- }
-
- LinkProperties linkProperties = mConnectivityManager.getLinkProperties(
- ConnectivityManager.TYPE_WIFI);
- if (linkProperties == null) return null;
-
- Collection<InetAddress> dnses = linkProperties.getDnses();
- if (dnses == null || dnses.size() == 0) return null;
-
- return dnses.iterator().next();
- }
-
- /**
- * Checks whether the DNS can be reached using multiple attempts according
- * to the current setting values.
- *
- * @return Whether the DNS is reachable
- */
- private boolean checkDnsConnectivity() {
- InetAddress dns = getDns();
- if (dns == null) {
- if (V) {
- myLogV("checkDnsConnectivity: Invalid DNS, returning false");
- }
- return false;
- }
-
- if (V) {
- myLogV("checkDnsConnectivity: Checking " + dns.getHostAddress() + " for connectivity");
- }
-
- int numInitialIgnoredPings = getInitialIgnoredPingCount();
- int numPings = getPingCount();
- int pingDelay = getPingDelayMs();
- int acceptableLoss = getAcceptablePacketLossPercentage();
-
- /** See {@link Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} */
- int ignoredPingCounter = 0;
- int pingCounter = 0;
- int successCounter = 0;
-
- // No connectivity check needed
- if (numPings == 0) {
- return true;
- }
-
- // Do the initial pings that we ignore
- for (; ignoredPingCounter < numInitialIgnoredPings; ignoredPingCounter++) {
- if (shouldCancel()) return false;
-
- boolean dnsAlive = DnsPinger.isDnsReachable(dns, getPingTimeoutMs());
- if (dnsAlive) {
- /*
- * Successful "ignored" pings are *not* ignored (they count in the total number
- * of pings), but failures are really ignored.
- */
-
- // TODO: This is confusing logic and should be rewitten
- // Here, successful 'ignored' pings are interpreted as a success in the below loop
- pingCounter++;
- successCounter++;
- }
-
- if (V) {
- Slog.v(TAG, (dnsAlive ? " +" : " Ignored: -"));
- }
-
- if (shouldCancel()) return false;
-
- try {
- Thread.sleep(pingDelay);
- } catch (InterruptedException e) {
- Slog.w(TAG, "Interrupted while pausing between pings", e);
- }
- }
-
- // Do the pings that we use to measure packet loss
- for (; pingCounter < numPings; pingCounter++) {
- if (shouldCancel()) return false;
-
- if (DnsPinger.isDnsReachable(dns, getPingTimeoutMs())) {
- successCounter++;
- if (V) {
- Slog.v(TAG, " +");
- }
- } else {
- if (V) {
- Slog.v(TAG, " -");
- }
- }
-
- if (shouldCancel()) return false;
-
- try {
- Thread.sleep(pingDelay);
- } catch (InterruptedException e) {
- Slog.w(TAG, "Interrupted while pausing between pings", e);
- }
- }
-
- //TODO: Integer division might cause problems down the road...
- int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
- if (D) {
- Slog.d(TAG, packetLossPercentage
- + "% packet loss (acceptable is " + acceptableLoss + "%)");
- }
-
- return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
- }
-
- private boolean backgroundCheckDnsConnectivity() {
- InetAddress dns = getDns();
-
- if (dns == null) {
- if (V) {
- myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
- }
- return false;
- }
-
- if (V) {
- myLogV("backgroundCheckDnsConnectivity: Background checking " +
- dns.getHostAddress() + " for connectivity");
- }
-
- return DnsPinger.isDnsReachable(dns, getBackgroundCheckTimeoutMs());
- }
-
- /**
- * Signals the current action to cancel.
- */
- private void cancelCurrentAction() {
- mShouldCancel = true;
- }
-
- /**
- * Helper to check whether to cancel.
- *
- * @return Whether to cancel processing the action.
- */
- private boolean shouldCancel() {
- if (V && mShouldCancel) {
- myLogV("shouldCancel: Cancelling");
- }
-
- return mShouldCancel;
- }
-
- // Wi-Fi initiated callbacks (could be executed in another thread)
-
- /**
- * Called when connected to an AP (this can be the next AP in line, or
- * it can be a completely different network).
- *
- * @param ssid The SSID of the access point.
- * @param bssid The BSSID of the access point.
- */
- private void onConnected(String ssid, String bssid) {
- if (V) {
- myLogV("onConnected: SSID: " + ssid + ", BSSID: " + bssid);
- }
-
- /*
- * The current action being processed by the main watchdog thread is now
- * stale, so cancel it.
- */
- cancelCurrentAction();
-
- if ((mSsid == null) || !mSsid.equals(ssid)) {
- /*
- * This is a different network than what the main watchdog thread is
- * processing, dispatch the network change message on the main thread.
- */
- mHandler.dispatchNetworkChanged(ssid);
- }
-
- if (requiresWatchdog(ssid, bssid)) {
- if (D) {
- myLogD(ssid + " (" + bssid + ") requires the watchdog");
- }
-
- // This access point requires a watchdog, so queue the check on the main thread
- mHandler.checkAp(new AccessPoint(ssid, bssid));
-
- } else {
- if (D) {
- myLogD(ssid + " (" + bssid + ") does not require the watchdog");
- }
-
- // This access point does not require a watchdog, so queue idle on the main thread
- mHandler.idle();
- }
- if (isWalledGardenTestEnabled()) mHandler.checkWalledGarden(ssid);
- }
-
- /**
- * Called when Wi-Fi is enabled.
- */
- private void onEnabled() {
- cancelCurrentAction();
- // Queue a hard-reset of the state on the main thread
- mHandler.reset();
- }
-
- /**
- * Called when disconnected (or some other event similar to being disconnected).
- */
- private void onDisconnected() {
- if (V) {
- myLogV("onDisconnected");
- }
-
- /*
- * Disconnected from an access point, the action being processed by the
- * watchdog thread is now stale, so cancel it.
- */
- cancelCurrentAction();
- // Dispatch the disconnected to the main watchdog thread
- mHandler.dispatchDisconnected();
- // Queue the action to go idle
- mHandler.idle();
- }
-
- /**
- * Checks whether an access point requires watchdog monitoring.
- *
- * @param ssid The SSID of the access point.
- * @param bssid The BSSID of the access point.
- * @return Whether the access point/network should be monitored by the
- * watchdog.
- */
- private boolean requiresWatchdog(String ssid, String bssid) {
- if (V) {
- myLogV("requiresWatchdog: SSID: " + ssid + ", BSSID: " + bssid);
- }
-
- WifiInfo info = null;
- if (ssid == null) {
- /*
- * This is called from a Wi-Fi callback, so assume the WifiInfo does
- * not have stale data.
- */
- info = mWifiManager.getConnectionInfo();
- ssid = info.getSSID();
- if (ssid == null) {
- // It's still null, give up
- if (V) {
- Slog.v(TAG, " Invalid SSID, returning false");
- }
- return false;
- }
- }
-
- if (TextUtils.isEmpty(bssid)) {
- // Similar as above
- if (info == null) {
- info = mWifiManager.getConnectionInfo();
- }
- bssid = info.getBSSID();
- if (TextUtils.isEmpty(bssid)) {
- // It's still null, give up
- if (V) {
- Slog.v(TAG, " Invalid BSSID, returning false");
- }
- return false;
- }
- }
-
- if (!isOnWatchList(ssid)) {
- if (V) {
- Slog.v(TAG, " SSID not on watch list, returning false");
- }
- return false;
- }
-
- // The watchdog only monitors networks with multiple APs
- if (!hasRequiredNumberOfAps(ssid)) {
- return false;
- }
-
- return true;
- }
-
- private boolean isOnWatchList(String ssid) {
- String watchList;
-
- if (ssid == null || (watchList = getWatchList()) == null) {
- return false;
- }
-
- String[] list = watchList.split(" *, *");
-
- for (String name : list) {
- if (ssid.equals(name)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Checks if the current scan results have multiple access points with an SSID.
- *
- * @param ssid The SSID to check.
- * @return Whether the SSID has multiple access points.
- */
- private boolean hasRequiredNumberOfAps(String ssid) {
- List<ScanResult> results = mWifiManager.getScanResults();
- if (results == null) {
- if (V) {
- myLogV("hasRequiredNumberOfAps: Got null scan results, returning false");
- }
- return false;
- }
-
- int numApsRequired = getApCount();
- int numApsFound = 0;
- int resultsSize = results.size();
- for (int i = 0; i < resultsSize; i++) {
- ScanResult result = results.get(i);
- if (result == null) continue;
- if (result.SSID == null) continue;
-
- if (result.SSID.equals(ssid)) {
- numApsFound++;
-
- if (numApsFound >= numApsRequired) {
- if (V) {
- myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning true");
- }
- return true;
- }
- }
- }
-
- if (V) {
- myLogV("hasRequiredNumberOfAps: SSID: " + ssid + ", returning false");
- }
- return false;
- }
-
- // Watchdog logic (assume all of these methods will be in our main thread)
-
- /**
- * Handles a Wi-Fi network change (for example, from networkA to networkB).
- */
- private void handleNetworkChanged(String ssid) {
- // Set the SSID being monitored to the new SSID
- mSsid = ssid;
- // Set various state to that when being idle
- setIdleState(true);
- }
-
- /**
- * Handles checking whether an AP is a "good" AP. If not, it will be blacklisted.
- *
- * @param ap The access point to check.
- */
- private void handleCheckAp(AccessPoint ap) {
- // Reset the cancel state since this is the entry point of this action
- mShouldCancel = false;
-
- if (V) {
- myLogV("handleCheckAp: AccessPoint: " + ap);
- }
-
- // Make sure we are not sleeping
- if (mState == WatchdogState.SLEEP) {
- if (V) {
- Slog.v(TAG, " Sleeping (in " + mSsid + "), so returning");
- }
- return;
- }
-
- mState = WatchdogState.CHECKING_AP;
-
- /*
- * Checks to make sure we haven't exceeded the max number of checks
- * we're allowed per network
- */
- incrementBssidCheckCount();
- if (getBssidCheckCount() > getMaxApChecks()) {
- if (V) {
- Slog.v(TAG, " Passed the max attempts (" + getMaxApChecks()
- + "), going to sleep for " + mSsid);
- }
- mHandler.sleep(mSsid);
- return;
- }
-
- // Do the check
- boolean isApAlive = checkDnsConnectivity();
-
- if (V) {
- Slog.v(TAG, " Is it alive: " + isApAlive);
- }
-
- // Take action based on results
- if (isApAlive) {
- handleApAlive(ap);
- } else {
- handleApUnresponsive(ap);
- }
- }
-
- /**
- * Handles the case when an access point is alive.
- *
- * @param ap The access point.
- */
- private void handleApAlive(AccessPoint ap) {
- // Check whether we are stale and should cancel
- if (shouldCancel()) return;
- // We're satisfied with this AP, so go idle
- setIdleState(false);
-
- if (D) {
- myLogD("AP is alive: " + ap.toString());
- }
-
- // Queue the next action to be a background check
- mHandler.backgroundCheckAp(ap);
- }
-
- /**
- * Handles an unresponsive AP by blacklisting it.
- *
- * @param ap The access point.
- */
- private void handleApUnresponsive(AccessPoint ap) {
- // Check whether we are stale and should cancel
- if (shouldCancel()) return;
- // This AP is "bad", switch to another
- mState = WatchdogState.SWITCHING_AP;
-
- if (D) {
- myLogD("AP is dead: " + ap.toString());
- }
-
- // Black list this "bad" AP, this will cause an attempt to connect to another
- blacklistAp(ap.bssid);
- // Initiate an association to an alternate AP
- mWifiManager.reassociate();
- }
-
- private void blacklistAp(String bssid) {
- if (TextUtils.isEmpty(bssid)) {
- return;
- }
-
- // Before taking action, make sure we should not cancel our processing
- if (shouldCancel()) return;
-
- mWifiManager.addToBlacklist(bssid);
-
- if (D) {
- myLogD("Blacklisting " + bssid);
- }
- }
-
- /**
- * Handles a single background check. If it fails, it should trigger a
- * normal check. If it succeeds, it should queue another background check.
- *
- * @param ap The access point to do a background check for. If this is no
- * longer the current AP, it is okay to return without any
- * processing.
- */
- private void handleBackgroundCheckAp(AccessPoint ap) {
- // Reset the cancel state since this is the entry point of this action
- mShouldCancel = false;
-
- if (V) {
- myLogV("handleBackgroundCheckAp: AccessPoint: " + ap);
- }
-
- // Make sure we are not sleeping
- if (mState == WatchdogState.SLEEP) {
- if (V) {
- Slog.v(TAG, " handleBackgroundCheckAp: Sleeping (in " + mSsid + "), so returning");
- }
- return;
- }
-
- // Make sure the AP we're supposed to be background checking is still the active one
- WifiInfo info = mWifiManager.getConnectionInfo();
- if (info.getSSID() == null || !info.getSSID().equals(ap.ssid)) {
- if (V) {
- myLogV("handleBackgroundCheckAp: We are no longer connected to "
- + ap + ", and instead are on " + info);
- }
- return;
- }
-
- if (info.getBSSID() == null || !info.getBSSID().equals(ap.bssid)) {
- if (V) {
- myLogV("handleBackgroundCheckAp: We are no longer connected to "
- + ap + ", and instead are on " + info);
- }
- return;
- }
-
- // Do the check
- boolean isApAlive = backgroundCheckDnsConnectivity();
-
- if (V && !isApAlive) {
- Slog.v(TAG, " handleBackgroundCheckAp: Is it alive: " + isApAlive);
- }
-
- if (shouldCancel()) {
- return;
- }
-
- // Take action based on results
- if (isApAlive) {
- // Queue another background check
- mHandler.backgroundCheckAp(ap);
-
- } else {
- if (D) {
- myLogD("Background check failed for " + ap.toString());
- }
-
- // Queue a normal check, so it can take proper action
- mHandler.checkAp(ap);
- }
- }
-
- /**
- * Handles going to sleep for this network. Going to sleep means we will not
- * monitor this network anymore.
- *
- * @param ssid The network that will not be monitored anymore.
- */
- private void handleSleep(String ssid) {
- // Make sure the network we're trying to sleep in is still the current network
- if (ssid != null && ssid.equals(mSsid)) {
- mState = WatchdogState.SLEEP;
-
- if (D) {
- myLogD("Going to sleep for " + ssid);
- }
-
- /*
- * Before deciding to go to sleep, we may have checked a few APs
- * (and blacklisted them). Clear the blacklist so the AP with best
- * signal is chosen.
- */
- mWifiManager.clearBlacklist();
-
- if (V) {
- myLogV("handleSleep: Set state to SLEEP and cleared blacklist");
- }
- }
- }
-
- /**
- * Handles an access point disconnection.
- */
- private void handleDisconnected() {
- /*
- * We purposefully do not change mSsid to null. This is to handle
- * disconnected followed by connected better (even if there is some
- * duration in between). For example, if the watchdog went to sleep in a
- * network, and then the phone goes to sleep, when the phone wakes up we
- * still want to be in the sleeping state. When the phone went to sleep,
- * we would have gotten a disconnected event which would then set mSsid
- * = null. This is bad, since the following connect would cause us to do
- * the "network is good?" check all over again. */
-
- /*
- * Set the state as if we were idle (don't come out of sleep, only
- * hard reset and network changed should do that.
- */
- setIdleState(false);
- }
-
- /**
- * Handles going idle. Idle means we are satisfied with the current state of
- * things, but if a new connection occurs we'll re-evaluate.
- */
- private void handleIdle() {
- // Reset the cancel state since this is the entry point for this action
- mShouldCancel = false;
-
- if (V) {
- myLogV("handleSwitchToIdle");
- }
-
- // If we're sleeping, don't do anything
- if (mState == WatchdogState.SLEEP) {
- Slog.v(TAG, " Sleeping (in " + mSsid + "), so returning");
- return;
- }
-
- // Set the idle state
- setIdleState(false);
-
- if (V) {
- Slog.v(TAG, " Set state to IDLE");
- }
- }
-
- /**
- * Sets the state as if we are going idle.
- */
- private void setIdleState(boolean forceIdleState) {
- // Setting idle state does not kick us out of sleep unless the forceIdleState is set
- if (forceIdleState || (mState != WatchdogState.SLEEP)) {
- mState = WatchdogState.IDLE;
- }
- resetBssidCheckCount();
- }
-
- /**
- * Handles a hard reset. A hard reset is rarely used, but when used it
- * should revert anything done by the watchdog monitoring.
- */
- private void handleReset() {
- mWifiManager.clearBlacklist();
- setIdleState(true);
- }
-
- // Inner classes
-
- /**
- * Possible states for the watchdog to be in.
- */
- private static enum WatchdogState {
- /** The watchdog is currently idle, but it is still responsive to future AP checks in this network. */
- IDLE,
- /** The watchdog is sleeping, so it will not try any AP checks for the network. */
- SLEEP,
- /** The watchdog is currently checking an AP for connectivity. */
- CHECKING_AP,
- /** The watchdog is switching to another AP in the network. */
- SWITCHING_AP
- }
-
- private int getBssidCheckCount() {
- return mBssidCheckCount;
- }
-
- private void incrementBssidCheckCount() {
- mBssidCheckCount++;
- }
-
- private void resetBssidCheckCount() {
- this.mBssidCheckCount = 0;
- }
-
- /**
- * The main thread for the watchdog monitoring. This will be turned into a
- * {@link Looper} thread.
- */
- private class WifiWatchdogThread extends Thread {
- WifiWatchdogThread() {
- super("WifiWatchdogThread");
- }
-
- @Override
- public void run() {
- // Set this thread up so the handler will work on it
- Looper.prepare();
-
- synchronized(WifiWatchdogService.this) {
- mHandler = new WifiWatchdogHandler();
-
- // Notify that the handler has been created
- WifiWatchdogService.this.notify();
- }
-
- // Listen for messages to the handler
- Looper.loop();
- }
- }
-
- /**
- * The main thread's handler. There are 'actions', and just general
- * 'messages'. There should only ever be one 'action' in the queue (aside
- * from the one being processed, if any). There may be multiple messages in
- * the queue. So, actions are replaced by more recent actions, where as
- * messages will be executed for sure. Messages end up being used to just
- * change some state, and not really take any action.
- * <p>
- * There is little logic inside this class, instead methods of the form
- * "handle___" are called in the main {@link WifiWatchdogService}.
- */
- private class WifiWatchdogHandler extends Handler {
- /** Check whether the AP is "good". The object will be an {@link AccessPoint}. */
- static final int ACTION_CHECK_AP = 1;
- /** Go into the idle state. */
- static final int ACTION_IDLE = 2;
- /**
- * Performs a periodic background check whether the AP is still "good".
- * The object will be an {@link AccessPoint}.
- */
- static final int ACTION_BACKGROUND_CHECK_AP = 3;
- /** Check whether the connection is a walled garden */
- static final int ACTION_CHECK_WALLED_GARDEN = 4;
-
- /**
- * Go to sleep for the current network. We are conservative with making
- * this a message rather than action. We want to make sure our main
- * thread sees this message, but if it were an action it could be
- * removed from the queue and replaced by another action. The main
- * thread will ensure when it sees the message that the state is still
- * valid for going to sleep.
- * <p>
- * For an explanation of sleep, see {@link android.provider.Settings.Secure#WIFI_WATCHDOG_MAX_AP_CHECKS}.
- */
- static final int MESSAGE_SLEEP = 101;
- /** Disables the watchdog. */
- static final int MESSAGE_DISABLE_WATCHDOG = 102;
- /** The network has changed. */
- static final int MESSAGE_NETWORK_CHANGED = 103;
- /** The current access point has disconnected. */
- static final int MESSAGE_DISCONNECTED = 104;
- /** Performs a hard-reset on the watchdog state. */
- static final int MESSAGE_RESET = 105;
-
- /* Walled garden detection */
- private String mLastSsid;
- private long mLastTime;
- private final long MIN_WALLED_GARDEN_TEST_INTERVAL = 15 * 60 * 1000; //15 minutes
-
- void checkWalledGarden(String ssid) {
- sendMessage(obtainMessage(ACTION_CHECK_WALLED_GARDEN, ssid));
- }
-
- void checkAp(AccessPoint ap) {
- removeAllActions();
- sendMessage(obtainMessage(ACTION_CHECK_AP, ap));
- }
-
- void backgroundCheckAp(AccessPoint ap) {
- if (!isBackgroundCheckEnabled()) return;
-
- removeAllActions();
- sendMessageDelayed(obtainMessage(ACTION_BACKGROUND_CHECK_AP, ap),
- getBackgroundCheckDelayMs());
- }
-
- void idle() {
- removeAllActions();
- sendMessage(obtainMessage(ACTION_IDLE));
- }
-
- void sleep(String ssid) {
- removeAllActions();
- sendMessage(obtainMessage(MESSAGE_SLEEP, ssid));
- }
-
- void disableWatchdog() {
- removeAllActions();
- sendMessage(obtainMessage(MESSAGE_DISABLE_WATCHDOG));
- }
-
- void dispatchNetworkChanged(String ssid) {
- removeAllActions();
- sendMessage(obtainMessage(MESSAGE_NETWORK_CHANGED, ssid));
- }
-
- void dispatchDisconnected() {
- removeAllActions();
- sendMessage(obtainMessage(MESSAGE_DISCONNECTED));
- }
-
- void reset() {
- removeAllActions();
- sendMessage(obtainMessage(MESSAGE_RESET));
- }
-
- private void removeAllActions() {
- removeMessages(ACTION_CHECK_AP);
- removeMessages(ACTION_IDLE);
- removeMessages(ACTION_BACKGROUND_CHECK_AP);
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (V) {
- myLogV("handleMessage: " + msg.what);
- }
- switch (msg.what) {
- case MESSAGE_NETWORK_CHANGED:
- handleNetworkChanged((String) msg.obj);
- break;
- case ACTION_CHECK_AP:
- handleCheckAp((AccessPoint) msg.obj);
- break;
- case ACTION_BACKGROUND_CHECK_AP:
- handleBackgroundCheckAp((AccessPoint) msg.obj);
- break;
- case ACTION_CHECK_WALLED_GARDEN:
- handleWalledGardenCheck((String) msg.obj);
- break;
- case MESSAGE_SLEEP:
- handleSleep((String) msg.obj);
- break;
- case ACTION_IDLE:
- handleIdle();
- break;
- case MESSAGE_DISABLE_WATCHDOG:
- handleIdle();
- break;
- case MESSAGE_DISCONNECTED:
- handleDisconnected();
- break;
- case MESSAGE_RESET:
- handleReset();
- break;
- }
- }
-
- /**
- * DNS based detection techniques do not work at all hotspots. The one sure way to check
- * a walled garden is to see if a URL fetch on a known address fetches the data we
- * expect
- */
- private boolean isWalledGardenConnection() {
- InputStream in = null;
- HttpURLConnection urlConnection = null;
- try {
- URL url = new URL(getWalledGardenUrl());
- urlConnection = (HttpURLConnection) url.openConnection();
- in = new BufferedInputStream(urlConnection.getInputStream());
- Scanner scanner = new Scanner(in);
- if (scanner.findInLine(getWalledGardenPattern()) != null) {
- return false;
- } else {
- return true;
- }
- } catch (IOException e) {
- return false;
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- }
- }
- if (urlConnection != null) urlConnection.disconnect();
- }
- }
-
- private void handleWalledGardenCheck(String ssid) {
- long currentTime = System.currentTimeMillis();
- //Avoid a walled garden test on the same network if one was already done
- //within MIN_WALLED_GARDEN_TEST_INTERVAL. This will handle scenarios where
- //there are frequent network disconnections
- if (ssid.equals(mLastSsid) &&
- (currentTime - mLastTime) < MIN_WALLED_GARDEN_TEST_INTERVAL) {
- return;
- }
-
- mLastTime = currentTime;
- mLastSsid = ssid;
-
- if (isWalledGardenConnection()) {
- Uri uri = Uri.parse("http://www.google.com");
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
- Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- }
- }
- }
-
- /**
- * Receives Wi-Fi broadcasts.
- * <p>
- * There is little logic in this class, instead methods of the form "on___"
- * are called in the {@link WifiWatchdogService}.
- */
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- handleNetworkStateChanged(
- (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN));
- }
- }
-
- private void handleNetworkStateChanged(NetworkInfo info) {
- if (V) {
- myLogV("Receiver.handleNetworkStateChanged: NetworkInfo: "
- + info);
- }
-
- switch (info.getState()) {
- case CONNECTED:
- WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) {
- if (V) {
- myLogV("handleNetworkStateChanged: Got connected event but SSID or BSSID are null. SSID: "
- + wifiInfo.getSSID()
- + ", BSSID: "
- + wifiInfo.getBSSID() + ", ignoring event");
- }
- return;
- }
- onConnected(wifiInfo.getSSID(), wifiInfo.getBSSID());
- break;
-
- case DISCONNECTED:
- onDisconnected();
- break;
- }
- }
-
- private void handleWifiStateChanged(int wifiState) {
- if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
- onDisconnected();
- } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
- onEnabled();
- }
- }
- };
-
- /**
- * Describes an access point by its SSID and BSSID.
- *
- */
- private static class AccessPoint {
- String ssid;
- String bssid;
-
- /**
- * @param ssid cannot be null
- * @param bssid cannot be null
- */
- AccessPoint(String ssid, String bssid) {
- if (ssid == null || bssid == null) {
- Slog.e(TAG, String.format("(%s) INVALID ACCESSPOINT: (%s, %s)",
- Thread.currentThread().getName(),ssid,bssid));
- }
- this.ssid = ssid;
- this.bssid = bssid;
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof AccessPoint)) return false;
- AccessPoint otherAp = (AccessPoint) o;
-
- // Either we both have a null, or our SSIDs and BSSIDs are equal
- return ssid.equals(otherAp.ssid) && bssid.equals(otherAp.bssid);
- }
-
- @Override
- public int hashCode() {
- return ssid.hashCode() + bssid.hashCode();
- }
-
- @Override
- public String toString() {
- return ssid + " (" + bssid + ")";
- }
- }
-
- /**
- * Performs a simple DNS "ping" by sending a "server status" query packet to
- * the DNS server. As long as the server replies, we consider it a success.
- * <p>
- * We do not use a simple hostname lookup because that could be cached and
- * the API may not differentiate between a time out and a failure lookup
- * (which we really care about).
- */
- private static class DnsPinger {
-
- /** Number of bytes for the query */
- private static final int DNS_QUERY_BASE_SIZE = 33;
-
- /** The DNS port */
- private static final int DNS_PORT = 53;
-
- /** Used to generate IDs */
- private static Random sRandom = new Random();
-
- static boolean isDnsReachable(InetAddress dnsAddress, int timeout) {
- DatagramSocket socket = null;
- try {
- socket = new DatagramSocket();
-
- // Set some socket properties
- socket.setSoTimeout(timeout);
-
- byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
- fillQuery(buf);
-
- // Send the DNS query
-
- DatagramPacket packet = new DatagramPacket(buf,
- buf.length, dnsAddress, DNS_PORT);
- socket.send(packet);
-
- // Wait for reply (blocks for the above timeout)
- DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
- socket.receive(replyPacket);
-
- // If a timeout occurred, an exception would have been thrown. We got a reply!
- return true;
-
- } catch (SocketException e) {
- if (V) {
- Slog.v(TAG, "DnsPinger.isReachable received SocketException", e);
- }
- return false;
-
- } catch (UnknownHostException e) {
- if (V) {
- Slog.v(TAG, "DnsPinger.isReachable is unable to resolve the DNS host", e);
- }
- return false;
-
- } catch (SocketTimeoutException e) {
- return false;
-
- } catch (IOException e) {
- if (V) {
- Slog.v(TAG, "DnsPinger.isReachable got an IOException", e);
- }
- return false;
-
- } catch (Exception e) {
- if (V) {
- Slog.d(TAG, "DnsPinger.isReachable got an unknown exception", e);
- }
- return false;
- } finally {
- if (socket != null) {
- socket.close();
- }
- }
- }
-
- private static void fillQuery(byte[] buf) {
-
- /*
- * See RFC2929 (though the bit tables in there are misleading for
- * us. For example, the recursion desired bit is the 0th bit for us,
- * but looking there it would appear as the 7th bit of the byte
- */
-
- // Make sure it's all zeroed out
- for (int i = 0; i < buf.length; i++) buf[i] = 0;
-
- // Form a query for www.android.com
-
- // [0-1] bytes are an ID, generate random ID for this query
- buf[0] = (byte) sRandom.nextInt(256);
- buf[1] = (byte) sRandom.nextInt(256);
-
- // [2-3] bytes are for flags.
- buf[2] = 1; // Recursion desired
-
- // [4-5] bytes are for the query count
- buf[5] = 1; // One query
-
- // [6-7] [8-9] [10-11] are all counts of other fields we don't use
-
- // [12-15] for www
- writeString(buf, 12, "www");
-
- // [16-23] for android
- writeString(buf, 16, "android");
-
- // [24-27] for com
- writeString(buf, 24, "com");
-
- // [29-30] bytes are for QTYPE, set to 1
- buf[30] = 1;
-
- // [31-32] bytes are for QCLASS, set to 1
- buf[32] = 1;
- }
-
- private static void writeString(byte[] buf, int startPos, String string) {
- int pos = startPos;
-
- // Write the length first
- buf[pos++] = (byte) string.length();
- for (int i = 0; i < string.length(); i++) {
- buf[pos++] = (byte) string.charAt(i);
- }
- }
+ Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1;
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index a9dfb22..10dd924 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -549,6 +550,26 @@
private void notifyEventListenerLocked(Service service, int eventType) {
IEventListener listener = service.mServiceInterface;
AccessibilityEvent event = service.mPendingEvents.get(eventType);
+
+ // Check for null here because there is a concurrent scenario in which this
+ // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
+ // which posts a message for dispatching an event. 2) The message is pulled
+ // from the queue by the handler on the service thread and the latter is
+ // just about to acquire the lock and call this method. 3) Now another binder
+ // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
+ // so the service thread waits for the lock; 4) The binder thread replaces
+ // the event with a more recent one (assume the same event type) and posts a
+ // dispatch request releasing the lock. 5) Now the main thread is unblocked and
+ // dispatches the event which is removed from the pending ones. 6) And ... now
+ // the service thread handles the last message posted by the last binder call
+ // but the event is already dispatched and hence looking it up in the pending
+ // ones yields null. This check is much simpler that keeping count for each
+ // event type of each service to catch such a scenario since only one message
+ // is processed at a time.
+ if (event == null) {
+ return;
+ }
+
service.mPendingEvents.remove(eventType);
try {
if (mSecurityPolicy.canRetrieveWindowContent(service)) {
@@ -814,6 +835,8 @@
final AtomicInteger mInteractionIdCounter = new AtomicInteger();
+ final Rect mTempBounds = new Rect();
+
// the events pending events to be dispatched to this service
final SparseArray<AccessibilityEvent> mPendingEvents =
new SparseArray<AccessibilityEvent>();
@@ -932,9 +955,10 @@
AccessibilityNodeInfo info = mCallback.getFindAccessibilityNodeInfoResultAndClear(
interactionId);
if (info != null) {
+ applyCompatibilityScaleIfNeeded(info);
info.setConnection(this);
+ info.setSealed(true);
}
- info.setSealed(true);
return info;
} catch (RemoteException re) {
if (DEBUG) {
@@ -979,6 +1003,7 @@
final int infoCount = infos.size();
for (int i = 0; i < infoCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
+ applyCompatibilityScaleIfNeeded(info);
info.setConnection(this);
info.setSealed(true);
}
@@ -1019,6 +1044,7 @@
AccessibilityNodeInfo info =
mCallback.getFindAccessibilityNodeInfoResultAndClear(interactionId);
if (info != null) {
+ applyCompatibilityScaleIfNeeded(info);
info.setConnection(this);
info.setSealed(true);
}
@@ -1093,6 +1119,24 @@
}
return mWindowIdToInteractionConnectionMap.get(windowId);
}
+
+ private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info) {
+ IBinder windowToken = mWindowIdToWindowTokenMap.get(info.getWindowId());
+ final float scale = mWindowManagerService.getWindowCompatibilityScale(windowToken);
+
+ if (scale == 1.0f) {
+ return;
+ }
+
+ Rect bounds = mTempBounds;
+ info.getBoundsInParent(bounds);
+ bounds.scale(scale);
+ info.setBoundsInParent(bounds);
+
+ info.getBoundsInScreen(bounds);
+ bounds.scale(scale);
+ info.setBoundsInScreen(bounds);
+ }
}
final class SecurityPolicy {
@@ -1107,7 +1151,9 @@
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
| AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
| AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
- | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+ | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_SCROLLED;
private int mRetrievalAlowingWindowId;
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index aab189a6..1af7015 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -26,7 +26,6 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
@@ -73,15 +72,6 @@
private static final int STATE_DRAGGING = 0x00000002;
private static final int STATE_DELEGATING = 0x00000004;
- // Human readable symbolic names for the states of the explorer.
- private static final SparseArray<String> sStateSymbolicNames = new SparseArray<String>();
- static {
- SparseArray<String> symbolicNames = sStateSymbolicNames;
- symbolicNames.append(STATE_TOUCH_EXPLORING, "STATE_TOUCH_EXPLORING");
- symbolicNames.append(STATE_DRAGGING, "STATE_DRAGING");
- symbolicNames.append(STATE_DELEGATING, "STATE_DELEGATING");
- }
-
// Invalid pointer ID.
private static final int INVALID_POINTER_ID = -1;
@@ -189,7 +179,7 @@
if (DEBUG) {
Slog.d(LOG_TAG_RECEIVED, "Received event: " + event + ", policyFlags=0x"
+ Integer.toHexString(policyFlags));
- Slog.d(LOG_TAG_STATE, sStateSymbolicNames.get(mCurrentState));
+ Slog.d(LOG_TAG_STATE, getStateSymbolicName(mCurrentState));
}
// Keep track of the pointers's state.
@@ -708,8 +698,7 @@
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
final PointerProperties[] pointerProperties = mTempPointerProperties;
final PointerCoords[] pointerCoords = mTempPointerCoords;
- final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
- final int pointerIndex = prototype.findPointerIndex(pointerId);
+ final int pointerIndex = prototype.getActionIndex();
// Send down.
prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
@@ -884,6 +873,25 @@
}
/**
+ * Gets the symbolic name of a state.
+ *
+ * @param state A state.
+ * @return The state symbolic name.
+ */
+ private static String getStateSymbolicName(int state) {
+ switch (state) {
+ case STATE_TOUCH_EXPLORING:
+ return "STATE_TOUCH_EXPLORING";
+ case STATE_DRAGGING:
+ return "STATE_DRAGGING";
+ case STATE_DELEGATING:
+ return "STATE_DELEGATING";
+ default:
+ throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ }
+
+ /**
* Helper class for tracking pointers and more specifically which of
* them are currently down, which are active, and which are delivered
* to the view hierarchy. The enclosing {@link TouchExplorer} uses the
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f1098a8..bf877f6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -622,6 +622,11 @@
}
return true;
}
+
+ @Override
+ protected String packageForFilter(BroadcastFilter filter) {
+ return filter.packageName;
+ }
};
/**
@@ -1825,6 +1830,8 @@
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
+ // If this is a new package in the process, add the package to the list
+ app.addPackage(info.packageName);
return app;
} else {
// An application record is attached to a previous process,
@@ -1933,6 +1940,9 @@
int debugFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+ // Also turn on CheckJNI for debuggable apps. It's quite
+ // awkward to turn on otherwise.
+ debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
@@ -2275,7 +2285,7 @@
}
}
- return pir.sendInner(0, fillInIntent, resolvedType,
+ return pir.sendInner(0, fillInIntent, resolvedType, null,
null, resultTo, resultWho, requestCode, flagsMask, flagsValues);
}
@@ -4159,6 +4169,27 @@
return null;
}
+ public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
+ if (!(pendingResult instanceof PendingIntentRecord)) {
+ return false;
+ }
+ try {
+ PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+ if (res.key.allIntents == null) {
+ return false;
+ }
+ for (int i=0; i<res.key.allIntents.length; i++) {
+ Intent intent = res.key.allIntents[i];
+ if (intent.getPackage() != null && intent.getComponent() != null) {
+ return false;
+ }
+ }
+ return true;
+ } catch (ClassCastException e) {
+ }
+ return false;
+ }
+
public void setProcessLimit(int max) {
enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
"setProcessLimit()");
@@ -9892,6 +9923,7 @@
ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
if (app != null && app.thread != null) {
try {
+ app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
return true;
} catch (RemoteException e) {
@@ -10942,7 +10974,7 @@
mBroadcastsScheduled = true;
}
- public Intent registerReceiver(IApplicationThread caller,
+ public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission) {
synchronized(this) {
ProcessRecord callerApp = null;
@@ -10954,6 +10986,13 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
+ if (callerApp.info.uid != Process.SYSTEM_UID &&
+ !callerApp.pkgList.contains(callerPackage)) {
+ throw new SecurityException("Given caller package " + callerPackage
+ + " is not running in process " + callerApp);
+ }
+ } else {
+ callerPackage = null;
}
List allSticky = null;
@@ -10998,7 +11037,7 @@
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
- BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
+ BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadast");
@@ -12152,6 +12191,7 @@
info.activityInfo.applicationInfo.uid);
if (app != null && app.thread != null) {
try {
+ app.addPackage(info.activityInfo.packageName);
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d8772b8..b1da69f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -73,7 +73,7 @@
*/
final class ActivityStack {
static final String TAG = ActivityManagerService.TAG;
- static final boolean localLOGV = ActivityManagerService.localLOGV || true;
+ static final boolean localLOGV = ActivityManagerService.localLOGV;
static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
@@ -652,6 +652,7 @@
if (app != null && app.thread != null) {
try {
+ app.addPackage(r.info.packageName);
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index a769c05..917259a 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -60,12 +60,12 @@
setCancelable(false);
- setButton(DialogInterface.BUTTON_POSITIVE,
+ setButton(DialogInterface.BUTTON_NEGATIVE,
res.getText(com.android.internal.R.string.force_close),
mHandler.obtainMessage(FORCE_QUIT));
if (app.errorReportReceiver != null) {
- setButton(DialogInterface.BUTTON_NEGATIVE,
+ setButton(DialogInterface.BUTTON_POSITIVE,
res.getText(com.android.internal.R.string.report),
mHandler.obtainMessage(FORCE_QUIT_AND_REPORT));
}
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index b2737dc..b40f87a 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -77,7 +77,7 @@
? res.getString(resid, name1.toString(), name2.toString())
: res.getString(resid, name1.toString()));
- setButton(DialogInterface.BUTTON_POSITIVE,
+ setButton(DialogInterface.BUTTON_NEGATIVE,
res.getText(com.android.internal.R.string.force_close),
mHandler.obtainMessage(FORCE_CLOSE));
setButton(DialogInterface.BUTTON_NEUTRAL,
@@ -85,7 +85,7 @@
mHandler.obtainMessage(WAIT));
if (app.errorReportReceiver != null) {
- setButton(DialogInterface.BUTTON_NEGATIVE,
+ setButton(DialogInterface.BUTTON_POSITIVE,
res.getText(com.android.internal.R.string.report),
mHandler.obtainMessage(WAIT_AND_REPORT));
}
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index b4fdc9f..293702d 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -446,6 +446,15 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
+ private void dumpHelp(PrintWriter pw) {
+ pw.println("Battery stats (batteryinfo) dump options:");
+ pw.println(" [--checkin] [--reset] [--write] [-h]");
+ pw.println(" --checkin: format output for a checkin report.");
+ pw.println(" --reset: reset the stats, clearing all current data.");
+ pw.println(" --write: force write current collected stats to disk.");
+ pw.println(" -h: print this help text.");
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
boolean isCheckin = false;
@@ -466,8 +475,12 @@
pw.println("Battery stats written.");
noOutput = true;
}
+ } else if ("-h".equals(arg)) {
+ dumpHelp(pw);
+ return;
} else {
pw.println("Unknown option: " + arg);
+ dumpHelp(pw);
}
}
}
diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java
index 2e784d3..b49bc22 100644
--- a/services/java/com/android/server/am/BroadcastFilter.java
+++ b/services/java/com/android/server/am/BroadcastFilter.java
@@ -25,12 +25,14 @@
class BroadcastFilter extends IntentFilter {
// Back-pointer to the list this filter is in.
final ReceiverList receiverList;
+ final String packageName;
final String requiredPermission;
BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList,
- String _requiredPermission) {
+ String _packageName, String _requiredPermission) {
super(_filter);
receiverList = _receiverList;
+ packageName = _packageName;
requiredPermission = _requiredPermission;
}
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index ee6e420..8ed0cc1 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -177,13 +177,13 @@
}
public int send(int code, Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver) {
+ IIntentReceiver finishedReceiver, String requiredPermission) {
return sendInner(code, intent, resolvedType, finishedReceiver,
- null, null, 0, 0, 0);
+ requiredPermission, null, null, 0, 0, 0);
}
int sendInner(int code, Intent intent, String resolvedType,
- IIntentReceiver finishedReceiver,
+ IIntentReceiver finishedReceiver, String requiredPermission,
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues) {
synchronized(owner) {
@@ -246,8 +246,8 @@
// that the broadcast be delivered synchronously
owner.broadcastIntentInPackage(key.packageName, uid,
finalIntent, resolvedType,
- finishedReceiver, code, null, null, null,
- (finishedReceiver != null), false);
+ finishedReceiver, code, null, null,
+ requiredPermission, (finishedReceiver != null), false);
sendFinish = false;
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 5fa26ef..6bb7949 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -57,7 +57,9 @@
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
/**
@@ -82,7 +84,15 @@
private String[] mTetherableUsbRegexs;
private String[] mTetherableWifiRegexs;
private String[] mTetherableBluetoothRegexs;
- private String[] mUpstreamIfaceRegexs;
+ private Collection<Integer> mUpstreamIfaceTypes;
+
+ private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
+ private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
+ private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
+
+ // if we have to connect to mobile, what APN type should we use? Calculated by examining the
+ // upstream type list and the DUN_REQUIRED secure-setting
+ private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
private INetworkManagementService mNMService;
private Looper mLooper;
@@ -112,9 +122,6 @@
private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
- // resampled each time we turn on tethering - used as cache for settings/config-val
- private boolean mDunRequired; // configuration info - must use DUN apn on 3g
-
private StateMachine mTetherMasterSM;
private Notification mTetheredNotification;
@@ -159,7 +166,6 @@
if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
mDhcpRange = DHCP_DEFAULT_RANGE;
}
- mDunRequired = false; // resample when we turn on
mTetherableUsbRegexs = context.getResources().getStringArray(
com.android.internal.R.array.config_tether_usb_regexs);
@@ -167,8 +173,15 @@
com.android.internal.R.array.config_tether_wifi_regexs);
mTetherableBluetoothRegexs = context.getResources().getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs);
- mUpstreamIfaceRegexs = context.getResources().getStringArray(
- com.android.internal.R.array.config_tether_upstream_regexs);
+ int ifaceTypes[] = context.getResources().getIntArray(
+ com.android.internal.R.array.config_tether_upstream_types);
+ mUpstreamIfaceTypes = new ArrayList();
+ for (int i : ifaceTypes) {
+ mUpstreamIfaceTypes.add(new Integer(i));
+ }
+
+ // check if the upstream type list needs to be modified due to secure-settings
+ checkDunRequired();
// TODO - remove and rely on real notifications of the current iface
mDnsServers = new String[2];
@@ -176,8 +189,8 @@
mDnsServers[1] = DNS_DEFAULT_SERVER2;
}
- public void interfaceLinkStatusChanged(String iface, boolean link) {
- if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
+ public void interfaceStatusChanged(String iface, boolean up) {
+ if (DEBUG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
boolean found = false;
boolean usb = false;
if (isWifi(iface)) {
@@ -192,7 +205,7 @@
synchronized (mIfaces) {
TetherInterfaceSM sm = mIfaces.get(iface);
- if (link) {
+ if (up) {
if (sm == null) {
sm = new TetherInterfaceSM(iface, mLooper, usb);
mIfaces.put(iface, sm);
@@ -207,6 +220,11 @@
}
}
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
+ interfaceStatusChanged(iface, up);
+ }
+
private boolean isUsb(String iface) {
for (String regex : mTetherableUsbRegexs) {
if (iface.matches(regex)) return true;
@@ -471,11 +489,20 @@
// used on cable insert/remove
private void enableUsbIfaces(boolean enable) {
+ // add/remove USB interfaces when USB is connected/disconnected
+ for (String intf : mTetherableUsbRegexs) {
+ if (enable) {
+ interfaceAdded(intf);
+ } else {
+ interfaceRemoved(intf);
+ }
+ }
+
String[] ifaces = new String[0];
try {
ifaces = mNMService.listInterfaces();
} catch (Exception e) {
- Log.e(TAG, "Error listing Interfaces :" + e);
+ Log.e(TAG, "Error listing Interfaces", e);
return;
}
for (String iface : ifaces) {
@@ -493,20 +520,19 @@
private boolean enableUsbRndis(boolean enabled) {
if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")");
+ UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
+ if (usbManager == null) {
+ Log.d(TAG, "could not get UsbManager");
+ return false;
+ }
try {
if (enabled) {
- synchronized (this) {
- if (!mNMService.isUsbRNDISStarted()) {
- mNMService.startUsbRNDIS();
- }
- }
+ usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
} else {
- if (mNMService.isUsbRNDISStarted()) {
- mNMService.stopUsbRNDIS();
- }
+ usbManager.setCurrentFunction(null, false);
}
} catch (Exception e) {
- Log.e(TAG, "Error toggling usb RNDIS :" + e);
+ Log.e(TAG, "Error toggling usb RNDIS", e);
return false;
}
return true;
@@ -516,35 +542,46 @@
private boolean configureUsbIface(boolean enabled) {
if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
- // bring toggle the interfaces
- String[] ifaces = new String[0];
- try {
- ifaces = mNMService.listInterfaces();
- } catch (Exception e) {
- Log.e(TAG, "Error listing Interfaces :" + e);
- return false;
+ if (enabled) {
+ // must enable RNDIS first to create the interface
+ enableUsbRndis(enabled);
}
- for (String iface : ifaces) {
- if (isUsb(iface)) {
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNMService.getInterfaceConfig(iface);
- if (ifcg != null) {
- InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
- ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
- if (enabled) {
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
- } else {
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
+
+ try {
+ // bring toggle the interfaces
+ String[] ifaces = new String[0];
+ try {
+ ifaces = mNMService.listInterfaces();
+ } catch (Exception e) {
+ Log.e(TAG, "Error listing Interfaces", e);
+ return false;
+ }
+ for (String iface : ifaces) {
+ if (isUsb(iface)) {
+ InterfaceConfiguration ifcg = null;
+ try {
+ ifcg = mNMService.getInterfaceConfig(iface);
+ if (ifcg != null) {
+ InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
+ ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
+ if (enabled) {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+ } else {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
+ }
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
+ mNMService.setInterfaceConfig(iface, ifcg);
}
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
- mNMService.setInterfaceConfig(iface, ifcg);
+ } catch (Exception e) {
+ Log.e(TAG, "Error configuring interface " + iface, e);
+ return false;
}
- } catch (Exception e) {
- Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
- return false;
}
+ }
+ } finally {
+ if (!enabled) {
+ enableUsbRndis(false);
}
}
@@ -563,16 +600,44 @@
return mTetherableBluetoothRegexs;
}
- public String[] getUpstreamIfaceRegexs() {
- return mUpstreamIfaceRegexs;
+ public int[] getUpstreamIfaceTypes() {
+ int values[] = new int[mUpstreamIfaceTypes.size()];
+ Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
+ for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
+ values[i] = iterator.next();
+ }
+ return values;
}
- public boolean isDunRequired() {
- boolean defaultVal = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_tether_dun_required);
- boolean result = (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1);
- return result;
+ public void checkDunRequired() {
+ int requiredApn = ((Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.TETHER_DUN_REQUIRED, 0) == 1) ?
+ ConnectivityManager.TYPE_MOBILE_DUN :
+ ConnectivityManager.TYPE_MOBILE_HIPRI);
+ if (mPreferredUpstreamMobileApn != requiredApn) {
+ if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
+ while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
+ mUpstreamIfaceTypes.remove(MOBILE_TYPE);
+ }
+ while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
+ mUpstreamIfaceTypes.remove(HIPRI_TYPE);
+ }
+ if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
+ mUpstreamIfaceTypes.add(DUN_TYPE);
+ }
+ } else {
+ while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
+ mUpstreamIfaceTypes.remove(DUN_TYPE);
+ }
+ if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
+ mUpstreamIfaceTypes.add(MOBILE_TYPE);
+ }
+ if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
+ mUpstreamIfaceTypes.add(HIPRI_TYPE);
+ }
+ }
+ mPreferredUpstreamMobileApn = requiredApn;
+ }
}
public String[] getTetheredIfaces() {
@@ -629,15 +694,12 @@
return retVal;
}
- public void handleTetherIfaceChange(String iface) {
- // check if iface is white listed
- for (String regex : mUpstreamIfaceRegexs) {
- if (iface.matches(regex)) {
- if (DEBUG) Log.d(TAG, "Tethering got Interface Change");
- mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface);
- break;
- }
- }
+ //TODO: Temporary handling upstream change triggered without
+ // CONNECTIVITY_ACTION. Only to accomodate interface
+ // switch during HO.
+ // @see bug/4455071
+ public void handleTetherIfaceChange() {
+ mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
}
class TetherInterfaceSM extends StateMachine {
@@ -853,17 +915,12 @@
transitionTo(mInitialState);
return;
}
- if (mUsb) Tethering.this.enableUsbRndis(true);
if (DEBUG) Log.d(TAG, "Tethered " + mIfaceName);
setAvailable(false);
setTethered(true);
sendTetherStateChangedBroadcast();
}
@Override
- public void exit() {
- if (mUsb) Tethering.this.enableUsbRndis(false);
- }
- @Override
public boolean processMessage(Message message) {
if (DEBUG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
boolean retValue = true;
@@ -1037,8 +1094,6 @@
static final int CMD_CELL_CONNECTION_RENEW = 4;
// we don't have a valid upstream conn, check again after a delay
static final int CMD_RETRY_UPSTREAM = 5;
- // received an indication that upstream interface has changed
- static final int CMD_IFACE_CHANGED = 6;
// This indicates what a timeout event relates to. A state that
// sends itself a delayed timeout event and handles incoming timeout events
@@ -1058,7 +1113,7 @@
private ArrayList mNotifyList;
private int mCurrentConnectionSequence;
- private boolean mMobileReserved = false;
+ private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
private String mUpstreamIfaceName = null;
@@ -1097,22 +1152,34 @@
public boolean processMessage(Message m) {
return false;
}
- protected boolean turnOnMobileConnection() {
+ protected String enableString(int apnType) {
+ switch (apnType) {
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ return Phone.FEATURE_ENABLE_DUN_ALWAYS;
+ case ConnectivityManager.TYPE_MOBILE:
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ return Phone.FEATURE_ENABLE_HIPRI;
+ }
+ return null;
+ }
+ protected boolean turnOnUpstreamMobileConnection(int apnType) {
boolean retValue = true;
- if (mMobileReserved) return retValue;
+ if (apnType == ConnectivityManager.TYPE_NONE) return false;
+ if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
int result = Phone.APN_REQUEST_FAILED;
+ String enableString = enableString(apnType);
+ if (enableString == null) return false;
try {
result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
- (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
- Phone.FEATURE_ENABLE_HIPRI), new Binder());
+ enableString, new Binder());
} catch (Exception e) {
}
switch (result) {
case Phone.APN_ALREADY_ACTIVE:
case Phone.APN_REQUEST_STARTED:
- mMobileReserved = true;
+ mMobileApnReserved = apnType;
Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
m.arg1 = ++mCurrentConnectionSequence;
sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
@@ -1125,18 +1192,17 @@
return retValue;
}
- protected boolean turnOffMobileConnection() {
- if (mMobileReserved) {
+ protected boolean turnOffUpstreamMobileConnection() {
+ if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
try {
cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
- (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
- Phone.FEATURE_ENABLE_HIPRI));
+ enableString(mMobileApnReserved));
} catch (Exception e) {
return false;
}
- mMobileReserved = false;
+ mMobileApnReserved = ConnectivityManager.TYPE_NONE;
}
return true;
}
@@ -1182,108 +1248,55 @@
transitionTo(mInitialState);
return true;
}
- protected String findActiveUpstreamIface() {
- // check for what iface we can use - if none found switch to error.
- IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
- IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
-
- try {
- LinkProperties defaultProp = cm.getActiveLinkProperties();
- if (defaultProp != null) {
- String iface = defaultProp.getInterfaceName();
- for(String regex : mUpstreamIfaceRegexs) {
- if (iface.matches(regex)) return iface;
- }
- }
- } catch (RemoteException e) { }
-
- String[] ifaces = new String[0];
- try {
- ifaces = mNMService.listInterfaces();
- } catch (Exception e) {
- Log.e(TAG, "Error listing Interfaces :" + e);
- return null;
- }
-
- for (String regex : mUpstreamIfaceRegexs) {
- for (String iface : ifaces) {
- if (iface.matches(regex)) {
- // verify it is active
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNMService.getInterfaceConfig(iface);
- if (ifcg.isActive()) {
- return iface;
- }
- } catch (Exception e) {
- Log.e(TAG, "Error getting iface config :" + e);
- // ignore - try next
- continue;
- }
- }
- }
- }
- return null;
- }
protected void chooseUpstreamType(boolean tryCell) {
- // decide if the current upstream is good or not and if not
- // do something about it (start up DUN if required or HiPri if not)
- String iface = findActiveUpstreamIface();
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
- mMobileReserved = false;
- if (DEBUG) {
- Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired ="
- + mDunRequired + ", iface=" + iface);
- }
- if (iface != null) {
+ int upType = ConnectivityManager.TYPE_NONE;
+ String iface = null;
+
+ for (Integer netType : mUpstreamIfaceTypes) {
+ NetworkInfo info = null;
try {
- if (mDunRequired) {
- // check if Dun is on - we can use that
- NetworkInfo info = cm.getNetworkInfo(
- ConnectivityManager.TYPE_MOBILE_DUN);
- if (info.isConnected()) {
- if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface);
- // even if we're already connected - it may be somebody else's
- // refcount, so add our own
- turnOnMobileConnection();
- } else {
- // verify the iface is not the default mobile - can't use that!
- info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
- if (info.isConnected()) {
- iface = null; // can't accept this one
- }
- }
- } else {
- if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection");
- NetworkInfo info = cm.getNetworkInfo(
- ConnectivityManager.TYPE_MOBILE_HIPRI);
- if (info.isConnected()) {
- if (DEBUG) Log.d(TAG, "yes - hipri in use");
- // even if we're already connected - it may be sombody else's
- // refcount, so add our own
- turnOnMobileConnection();
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException calling ConnectivityManager " + e);
- iface = null;
+ info = cm.getNetworkInfo(netType.intValue());
+ } catch (RemoteException e) { }
+ if ((info != null) && info.isConnected()) {
+ upType = netType.intValue();
+ break;
}
}
- // may have been set to null in the if above
- if (iface == null ) {
- boolean success = false;
- if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
- success = turnOnMobileConnection();
+
+ if (DEBUG) {
+ Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
+ + mPreferredUpstreamMobileApn + ", got type=" + upType);
+ }
+
+ // if we're on DUN, put our own grab on it
+ if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
+ upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
+ turnOnUpstreamMobileConnection(upType);
+ }
+
+ if (upType == ConnectivityManager.TYPE_NONE) {
+ boolean tryAgainLater = true;
+ if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
+ (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
+ // we think mobile should be coming up - don't set a retry
+ tryAgainLater = false;
}
- if (!success) {
- // wait for things to settle and retry
+ if (tryAgainLater) {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
+ } else {
+ LinkProperties linkProperties = null;
+ try {
+ linkProperties = cm.getLinkProperties(upType);
+ } catch (RemoteException e) { }
+ if (linkProperties != null) iface = linkProperties.getInterfaceName();
}
notifyTetheredOfNewUpstreamIface(iface);
}
+
protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
mUpstreamIfaceName = ifaceName;
@@ -1298,7 +1311,6 @@
class InitialState extends TetherMasterUtilState {
@Override
public void enter() {
- mMobileReserved = false;
}
@Override
public boolean processMessage(Message message) {
@@ -1306,7 +1318,7 @@
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_MODE_REQUESTED:
- mDunRequired = isDunRequired();
+ checkDunRequired();
TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString());
mNotifyList.add(who);
@@ -1340,7 +1352,7 @@
}
@Override
public void exit() {
- turnOffMobileConnection();
+ turnOffUpstreamMobileConnection();
notifyTetheredOfNewUpstreamIface(null);
}
@Override
@@ -1378,19 +1390,13 @@
Log.d(TAG, "renewing mobile connection - requeuing for another " +
CELL_CONNECTION_RENEW_MS + "ms");
}
- mMobileReserved = false; // need to renew it
- turnOnMobileConnection();
+ turnOnUpstreamMobileConnection(mMobileApnReserved);
}
break;
case CMD_RETRY_UPSTREAM:
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
break;
- case CMD_IFACE_CHANGED:
- String iface = (String)message.obj;
- if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface);
- notifyTetheredOfNewUpstreamIface(iface);
- break;
default:
retValue = false;
break;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 372ba85..54bddb2 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -18,7 +18,6 @@
import android.app.Notification;
import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -28,15 +27,23 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.net.INetworkManagementEventObserver;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.SystemProperties;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.net.VpnConfig;
import com.android.server.ConnectivityService.VpnCallback;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charsets;
+
/**
* @hide
*/
@@ -50,7 +57,8 @@
private String mPackageName;
private String mInterfaceName;
- private String mDnsPropertyPrefix;
+
+ private LegacyVpnRunner mLegacyVpnRunner;
public Vpn(Context context, VpnCallback callback) {
mContext = context;
@@ -64,42 +72,61 @@
* @return The name of the current prepared package.
*/
public synchronized String prepare(String packageName) {
-
- // TODO: Check if the caller is VpnDialogs.
-
+ // Return the current prepared package if the new one is null.
if (packageName == null) {
return mPackageName;
}
- // Check the permission of the given application.
+ // Check the permission of the caller.
PackageManager pm = mContext.getPackageManager();
- if (pm.checkPermission(VPN, packageName) != PackageManager.PERMISSION_GRANTED) {
+ VpnConfig.enforceCallingPackage(pm.getNameForUid(Binder.getCallingUid()));
+
+ // Check the permission of the given package.
+ if (packageName.isEmpty()) {
+ packageName = null;
+ } else if (pm.checkPermission(VPN, packageName) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(packageName + " does not have " + VPN);
}
// Reset the interface and hide the notification.
if (mInterfaceName != null) {
- nativeReset(mInterfaceName);
- mInterfaceName = null;
+ jniResetInterface(mInterfaceName);
+ mCallback.restore();
hideNotification();
- // TODO: Send out a broadcast.
+ mInterfaceName = null;
}
+ // Notify the package being revoked.
+ if (mPackageName != null) {
+ Intent intent = new Intent(VpnConfig.ACTION_VPN_REVOKED);
+ intent.setPackage(mPackageName);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcast(intent);
+ }
+
+ Log.i(TAG, "Switched from " + mPackageName + " to " + packageName);
mPackageName = packageName;
- Log.i(TAG, "Prepared for " + packageName);
return mPackageName;
}
/**
* Protect a socket from routing changes by binding it to the given
- * interface. The socket is NOT closed by this method.
+ * interface. The socket IS closed by this method.
*
* @param socket The socket to be bound.
* @param name The name of the interface.
*/
public void protect(ParcelFileDescriptor socket, String name) {
- mContext.enforceCallingPermission(VPN, "protect");
- nativeProtect(socket.getFd(), name);
+ try {
+ mContext.enforceCallingPermission(VPN, "protect");
+ jniProtectSocket(socket.getFd(), name);
+ } finally {
+ try {
+ socket.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
}
/**
@@ -118,24 +145,29 @@
try {
app = pm.getApplicationInfo(mPackageName, 0);
} catch (Exception e) {
- throw new SecurityException("Not prepared");
+ return null;
}
if (Binder.getCallingUid() != app.uid) {
- throw new SecurityException("Not prepared");
+ return null;
}
// Create and configure the interface.
- ParcelFileDescriptor descriptor = ParcelFileDescriptor.adoptFd(
- nativeEstablish(config.mtu, config.addresses, config.routes));
+ ParcelFileDescriptor descriptor =
+ ParcelFileDescriptor.adoptFd(jniCreateInterface(config.mtu));
- // Replace the interface and abort if it fails.
+ // Abort if any of the following steps fails.
try {
- String interfaceName = nativeGetName(descriptor.getFd());
-
- if (mInterfaceName != null && !mInterfaceName.equals(interfaceName)) {
- nativeReset(mInterfaceName);
+ String name = jniGetInterfaceName(descriptor.getFd());
+ if (jniSetAddresses(name, config.addresses) < 1) {
+ throw new IllegalArgumentException("At least one address must be specified");
}
- mInterfaceName = interfaceName;
+ if (config.routes != null) {
+ jniSetRoutes(name, config.routes);
+ }
+ if (mInterfaceName != null && !mInterfaceName.equals(name)) {
+ jniResetInterface(mInterfaceName);
+ }
+ mInterfaceName = name;
} catch (RuntimeException e) {
try {
descriptor.close();
@@ -148,12 +180,18 @@
String dnsServers = (config.dnsServers == null) ? "" : config.dnsServers.trim();
mCallback.override(dnsServers.isEmpty() ? null : dnsServers.split(" "));
- showNotification(pm, app, config.sessionName);
+ config.packageName = mPackageName;
+ config.interfaceName = mInterfaceName;
+ showNotification(pm, app, config);
return descriptor;
}
// INetworkManagementEventObserver.Stub
- public void interfaceLinkStatusChanged(String name, boolean up) {
+ public void interfaceStatusChanged(String name, boolean up) {
+ }
+
+ // INetworkManagementEventObserver.Stub
+ public void interfaceLinkStateChanged(String name, boolean up) {
}
// INetworkManagementEventObserver.Stub
@@ -162,14 +200,14 @@
// INetworkManagementEventObserver.Stub
public synchronized void interfaceRemoved(String name) {
- if (name.equals(mInterfaceName) && nativeCheck(name) == 0) {
+ if (name.equals(mInterfaceName) && jniCheckInterface(name) == 0) {
hideNotification();
mInterfaceName = null;
mCallback.restore();
}
}
- private void showNotification(PackageManager pm, ApplicationInfo app, String sessionName) {
+ private void showNotification(PackageManager pm, ApplicationInfo app, VpnConfig config) {
NotificationManager nm = (NotificationManager)
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -190,20 +228,9 @@
// Load the label.
String label = app.loadLabel(pm).toString();
- // Build the intent.
- // TODO: move these into VpnBuilder.
- Intent intent = new Intent();
- intent.setClassName("com.android.vpndialogs",
- "com.android.vpndialogs.ManageDialog");
- intent.putExtra("packageName", mPackageName);
- intent.putExtra("interfaceName", mInterfaceName);
- intent.putExtra("session", sessionName);
- intent.putExtra("startTime", android.os.SystemClock.elapsedRealtime());
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
// Build the notification.
- String text = (sessionName == null) ? mContext.getString(R.string.vpn_text) :
- mContext.getString(R.string.vpn_text_long, sessionName);
+ String text = (config.sessionName == null) ? mContext.getString(R.string.vpn_text) :
+ mContext.getString(R.string.vpn_text_long, config.sessionName);
long identity = Binder.clearCallingIdentity();
Notification notification = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.vpn_connected)
@@ -211,7 +238,7 @@
.setTicker(mContext.getString(R.string.vpn_ticker, label))
.setContentTitle(mContext.getString(R.string.vpn_title, label))
.setContentText(text)
- .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0))
+ .setContentIntent(VpnConfig.getIntentForNotification(mContext, config))
.setDefaults(Notification.DEFAULT_ALL)
.setOngoing(true)
.getNotification();
@@ -231,9 +258,202 @@
}
}
- private native int nativeEstablish(int mtu, String addresses, String routes);
- private native String nativeGetName(int fd);
- private native void nativeReset(String name);
- private native int nativeCheck(String name);
- private native void nativeProtect(int fd, String name);
+ private native int jniCreateInterface(int mtu);
+ private native String jniGetInterfaceName(int fd);
+ private native int jniSetAddresses(String name, String addresses);
+ private native int jniSetRoutes(String name, String routes);
+ private native void jniResetInterface(String name);
+ private native int jniCheckInterface(String name);
+ private native void jniProtectSocket(int fd, String name);
+
+ /**
+ * Handle legacy VPN requests. This method stops the services and restart
+ * them if their arguments are not null. Heavy things are offloaded to
+ * another thread, so callers will not be blocked too long.
+ *
+ * @param raoocn The arguments to be passed to racoon.
+ * @param mtpd The arguments to be passed to mtpd.
+ */
+ public synchronized void doLegacyVpn(String[] racoon, String[] mtpd) {
+ // Currently only system user is allowed.
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Unauthorized Caller");
+ }
+
+ // If the previous runner is still alive, interrupt it.
+ if (mLegacyVpnRunner != null && mLegacyVpnRunner.isAlive()) {
+ mLegacyVpnRunner.interrupt();
+ }
+
+ // Start a new runner and we are done!
+ mLegacyVpnRunner = new LegacyVpnRunner(
+ new String[] {"racoon", "mtpd"}, racoon, mtpd);
+ mLegacyVpnRunner.start();
+ }
+
+ /**
+ * Bringing up a VPN connection takes time, and that is all this thread
+ * does. Here we have plenty of time. The only thing we need to take
+ * care of is responding to interruptions as soon as possible. Otherwise
+ * requests will be piled up. This can be done in a Handler as a state
+ * machine, but it is much easier to read in the current form.
+ */
+ private class LegacyVpnRunner extends Thread {
+ private static final String TAG = "LegacyVpnRunner";
+
+ private static final String NONE = "--";
+
+ private final String[] mServices;
+ private final String[][] mArguments;
+ private long mTimer = -1;
+
+ public LegacyVpnRunner(String[] services, String[]... arguments) {
+ super(TAG);
+ mServices = services;
+ mArguments = arguments;
+ }
+
+ @Override
+ public void run() {
+ // Wait for the previous thread since it has been interrupted.
+ Log.v(TAG, "wait");
+ synchronized (TAG) {
+ Log.v(TAG, "run");
+ execute();
+ Log.v(TAG, "exit");
+ }
+ }
+
+ private void checkpoint(boolean yield) throws InterruptedException {
+ long now = SystemClock.elapsedRealtime();
+ if (mTimer == -1) {
+ mTimer = now;
+ Thread.sleep(1);
+ } else if (now - mTimer <= 30000) {
+ Thread.sleep(yield ? 200 : 1);
+ } else {
+ throw new InterruptedException("timeout");
+ }
+ }
+
+ private void execute() {
+ // Catch all exceptions so we can clean up few things.
+ try {
+ // Initialize the timer.
+ checkpoint(false);
+
+ // First stop the services.
+ for (String service : mServices) {
+ SystemProperties.set("ctl.stop", service);
+ }
+
+ // Wait for the services to stop.
+ for (String service : mServices) {
+ String key = "init.svc." + service;
+ while (!"stopped".equals(SystemProperties.get(key))) {
+ checkpoint(true);
+ }
+ }
+
+ // Reset the properties.
+ SystemProperties.set("vpn.dns", NONE);
+ SystemProperties.set("vpn.via", NONE);
+ while (!NONE.equals(SystemProperties.get("vpn.dns")) ||
+ !NONE.equals(SystemProperties.get("vpn.via"))) {
+ checkpoint(true);
+ }
+
+ // Check if we need to restart some services.
+ boolean restart = false;
+ for (String[] arguments : mArguments) {
+ restart = restart || (arguments != null);
+ }
+ if (!restart) {
+ return;
+ }
+
+ // Start the service with arguments.
+ for (int i = 0; i < mServices.length; ++i) {
+ String[] arguments = mArguments[i];
+ if (arguments == null) {
+ continue;
+ }
+
+ // Start the service.
+ String service = mServices[i];
+ SystemProperties.set("ctl.start", service);
+
+ // Wait for the service to start.
+ String key = "init.svc." + service;
+ while (!"running".equals(SystemProperties.get(key))) {
+ checkpoint(true);
+ }
+
+ // Create the control socket.
+ LocalSocket socket = new LocalSocket();
+ LocalSocketAddress address = new LocalSocketAddress(
+ service, LocalSocketAddress.Namespace.RESERVED);
+
+ // Wait for the socket to connect.
+ while (true) {
+ try {
+ socket.connect(address);
+ break;
+ } catch (Exception e) {
+ // ignore
+ }
+ checkpoint(true);
+ }
+ socket.setSoTimeout(500);
+
+ // Send over the arguments.
+ OutputStream output = socket.getOutputStream();
+ for (String argument : arguments) {
+ byte[] bytes = argument.getBytes(Charsets.UTF_8);
+ if (bytes.length >= 0xFFFF) {
+ throw new IllegalArgumentException("argument too large");
+ }
+ output.write(bytes.length >> 8);
+ output.write(bytes.length);
+ output.write(bytes);
+ checkpoint(false);
+ }
+
+ // Send End-Of-Arguments.
+ output.write(0xFF);
+ output.write(0xFF);
+ output.flush();
+ socket.close();
+ }
+
+ // Now here is the beast from the old days. We check few
+ // properties to figure out the current status. Ideally we
+ // can read things back from the sockets and get rid of the
+ // properties, but we have no time...
+ while (NONE.equals(SystemProperties.get("vpn.dns")) ||
+ NONE.equals(SystemProperties.get("vpn.via"))) {
+
+ // Check if a running service is dead.
+ for (int i = 0; i < mServices.length; ++i) {
+ String service = mServices[i];
+ if (mArguments[i] != null && !"running".equals(
+ SystemProperties.get("init.svc." + service))) {
+ throw new IllegalArgumentException(service + " is dead");
+ }
+ }
+ checkpoint(true);
+ }
+
+ // Great! Now we are connected!
+ Log.i(TAG, "connected!");
+ // TODO:
+
+ } catch (Exception e) {
+ Log.i(TAG, e.getMessage());
+ for (String service : mServices) {
+ SystemProperties.set("ctl.stop", service);
+ }
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 67e73f5f..4fa3bda 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -132,7 +132,7 @@
private static final int GPS_CAPABILITY_MSB = 0x0000002;
private static final int GPS_CAPABILITY_MSA = 0x0000004;
private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
-
+ private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
// these need to match AGpsType enum in gps.h
private static final int AGPS_TYPE_SUPL = 1;
@@ -200,6 +200,9 @@
private boolean mInjectNtpTimePending = true;
private boolean mDownloadXtraDataPending = true;
+ // set to true if the GPS engine does not do on-demand NTP time requests
+ private boolean mPeriodicTimeInjection;
+
// true if GPS is navigating
private boolean mNavigating;
@@ -549,10 +552,12 @@
delay = RETRY_INTERVAL;
}
- // send delayed message for next NTP injection
- // since this is delayed and not urgent we do not hold a wake lock here
- mHandler.removeMessages(INJECT_NTP_TIME);
- mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+ if (mPeriodicTimeInjection) {
+ // send delayed message for next NTP injection
+ // since this is delayed and not urgent we do not hold a wake lock here
+ mHandler.removeMessages(INJECT_NTP_TIME);
+ mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
+ }
}
private void handleDownloadXtraData() {
@@ -1305,6 +1310,11 @@
*/
private void setEngineCapabilities(int capabilities) {
mEngineCapabilities = capabilities;
+
+ if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
+ mPeriodicTimeInjection = true;
+ requestUtcTime();
+ }
}
/**
@@ -1438,6 +1448,14 @@
}
/**
+ * Called from native code to request utc time info
+ */
+
+ private void requestUtcTime() {
+ sendMessage(INJECT_NTP_TIME, 0, null);
+ }
+
+ /**
* Called from native code to request reference location info
*/
diff --git a/services/java/com/android/server/net/InterfaceIdentity.java b/services/java/com/android/server/net/InterfaceIdentity.java
deleted file mode 100644
index ff86581..0000000
--- a/services/java/com/android/server/net/InterfaceIdentity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.server.net;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.ProtocolException;
-import java.util.HashSet;
-
-/**
- * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
- * active on that interface.
- *
- * @hide
- */
-public class InterfaceIdentity extends HashSet<NetworkIdentity> {
- private static final int VERSION_CURRENT = 1;
-
- public InterfaceIdentity() {
- }
-
- public InterfaceIdentity(DataInputStream in) throws IOException {
- final int version = in.readInt();
- switch (version) {
- case VERSION_CURRENT: {
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- add(new NetworkIdentity(in));
- }
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- }
-
- public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_CURRENT);
- out.writeInt(size());
- for (NetworkIdentity ident : this) {
- ident.writeToStream(out);
- }
- }
-
- /**
- * Test if any {@link NetworkIdentity} on this interface matches the given
- * template and IMEI.
- */
- public boolean matchesTemplate(int networkTemplate, String subscriberId) {
- for (NetworkIdentity ident : this) {
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/services/java/com/android/server/net/NetworkIdentity.java b/services/java/com/android/server/net/NetworkIdentity.java
deleted file mode 100644
index 4a207f7..0000000
--- a/services/java/com/android/server/net/NetworkIdentity.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * 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.server.net;
-
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.ConnectivityManager.isNetworkTypeMobile;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_4G;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
-import static android.net.TrafficStats.TEMPLATE_WIFI;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
-import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
-import static android.telephony.TelephonyManager.getNetworkClass;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.net.NetworkState;
-import android.telephony.TelephonyManager;
-
-import com.android.internal.util.Objects;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.ProtocolException;
-
-/**
- * Identity of a {@link NetworkInfo}, defined by network type and billing
- * relationship (such as IMSI).
- *
- * @hide
- */
-public class NetworkIdentity {
- private static final int VERSION_CURRENT = 1;
-
- public final int type;
- public final int subType;
- public final String subscriberId;
-
- public NetworkIdentity(int type, int subType, String subscriberId) {
- this.type = type;
- this.subType = subType;
- this.subscriberId = subscriberId;
- }
-
- public NetworkIdentity(DataInputStream in) throws IOException {
- final int version = in.readInt();
- switch (version) {
- case VERSION_CURRENT: {
- type = in.readInt();
- subType = in.readInt();
- subscriberId = readOptionalString(in);
- break;
- }
- default: {
- throw new ProtocolException("unexpected version: " + version);
- }
- }
- }
-
- public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_CURRENT);
- out.writeInt(type);
- out.writeInt(subType);
- writeOptionalString(out, subscriberId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(type, subType, subscriberId);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof NetworkIdentity) {
- final NetworkIdentity ident = (NetworkIdentity) obj;
- return type == ident.type && subType == ident.subType
- && Objects.equal(subscriberId, ident.subscriberId);
- }
- return false;
- }
-
- @Override
- public String toString() {
- final String typeName = ConnectivityManager.getNetworkTypeName(type);
- final String subTypeName;
- if (ConnectivityManager.isNetworkTypeMobile(type)) {
- subTypeName = TelephonyManager.getNetworkTypeName(subType);
- } else {
- subTypeName = Integer.toString(subType);
- }
-
- return "[type=" + typeName + ", subType=" + subTypeName + ", subId=" + subscriberId + "]";
- }
-
- /**
- * Test if this network matches the given template and IMEI.
- */
- public boolean matchesTemplate(int networkTemplate, String subscriberId) {
- switch (networkTemplate) {
- case TEMPLATE_MOBILE_ALL:
- return matchesMobile(subscriberId);
- case TEMPLATE_MOBILE_3G_LOWER:
- return matchesMobile3gLower(subscriberId);
- case TEMPLATE_MOBILE_4G:
- return matchesMobile4g(subscriberId);
- case TEMPLATE_WIFI:
- return matchesWifi();
- default:
- throw new IllegalArgumentException("unknown network template");
- }
- }
-
- /**
- * Check if mobile network with matching IMEI. Also matches
- * {@link #TYPE_WIMAX}.
- */
- private boolean matchesMobile(String subscriberId) {
- if (isNetworkTypeMobile(type) && Objects.equal(this.subscriberId, subscriberId)) {
- return true;
- } else if (type == TYPE_WIMAX) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if mobile network classified 3G or lower with matching IMEI.
- */
- private boolean matchesMobile3gLower(String subscriberId) {
- if (isNetworkTypeMobile(type)
- && Objects.equal(this.subscriberId, subscriberId)) {
- switch (getNetworkClass(subType)) {
- case NETWORK_CLASS_UNKNOWN:
- case NETWORK_CLASS_2_G:
- case NETWORK_CLASS_3_G:
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check if mobile network classified 4G with matching IMEI. Also matches
- * {@link #TYPE_WIMAX}.
- */
- private boolean matchesMobile4g(String subscriberId) {
- if (isNetworkTypeMobile(type)
- && Objects.equal(this.subscriberId, subscriberId)) {
- switch (getNetworkClass(subType)) {
- case NETWORK_CLASS_4_G:
- return true;
- }
- } else if (type == TYPE_WIMAX) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if matches Wi-Fi network template.
- */
- private boolean matchesWifi() {
- if (type == TYPE_WIFI) {
- return true;
- }
- return false;
- }
-
- /**
- * Build a {@link NetworkIdentity} from the given {@link NetworkState},
- * assuming that any mobile networks are using the current IMSI.
- */
- public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
- final int type = state.networkInfo.getType();
- final int subType = state.networkInfo.getSubtype();
-
- // TODO: consider moving subscriberId over to LinkCapabilities, so it
- // comes from an authoritative source.
-
- final String subscriberId;
- if (isNetworkTypeMobile(type)) {
- final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE);
- subscriberId = telephony.getSubscriberId();
- } else {
- subscriberId = null;
- }
- return new NetworkIdentity(type, subType, subscriberId);
- }
-
- private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
- if (value != null) {
- out.writeByte(1);
- out.writeUTF(value);
- } else {
- out.writeByte(0);
- }
- }
-
- private static String readOptionalString(DataInputStream in) throws IOException {
- if (in.readByte() != 0) {
- return in.readUTF();
- } else {
- return null;
- }
- }
-
-}
diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/java/com/android/server/net/NetworkIdentitySet.java
new file mode 100644
index 0000000..af03fb3
--- /dev/null
+++ b/services/java/com/android/server/net/NetworkIdentitySet.java
@@ -0,0 +1,98 @@
+/*
+ * 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.server.net;
+
+import android.net.NetworkIdentity;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.util.HashSet;
+
+/**
+ * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
+ * active on that interface.
+ *
+ * @hide
+ */
+public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
+ private static final int VERSION_INIT = 1;
+ private static final int VERSION_ADD_ROAMING = 2;
+
+ public NetworkIdentitySet() {
+ }
+
+ public NetworkIdentitySet(DataInputStream in) throws IOException {
+ final int version = in.readInt();
+ switch (version) {
+ case VERSION_INIT: {
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ final int ignoredVersion = in.readInt();
+ final int type = in.readInt();
+ final int subType = in.readInt();
+ final String subscriberId = readOptionalString(in);
+ add(new NetworkIdentity(type, subType, subscriberId, false));
+ }
+ break;
+ }
+ case VERSION_ADD_ROAMING: {
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ final int type = in.readInt();
+ final int subType = in.readInt();
+ final String subscriberId = readOptionalString(in);
+ final boolean roaming = in.readBoolean();
+ add(new NetworkIdentity(type, subType, subscriberId, roaming));
+ }
+ break;
+ }
+ default: {
+ throw new ProtocolException("unexpected version: " + version);
+ }
+ }
+ }
+
+ public void writeToStream(DataOutputStream out) throws IOException {
+ out.writeInt(VERSION_ADD_ROAMING);
+ out.writeInt(size());
+ for (NetworkIdentity ident : this) {
+ out.writeInt(ident.getType());
+ out.writeInt(ident.getSubType());
+ writeOptionalString(out, ident.getSubscriberId());
+ out.writeBoolean(ident.getRoaming());
+ }
+ }
+
+ private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
+ if (value != null) {
+ out.writeByte(1);
+ out.writeUTF(value);
+ } else {
+ out.writeByte(0);
+ }
+ }
+
+ private static String readOptionalString(DataInputStream in) throws IOException {
+ if (in.readByte() != 0) {
+ return in.readUTF();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 9cbe82d..1f2ec2c 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -22,24 +22,27 @@
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.*;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_WARNING;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.dumpPolicy;
import static android.net.NetworkPolicyManager.dumpRules;
import static android.net.NetworkPolicyManager.isUidValidForPolicy;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_3G_LOWER;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_4G;
-import static android.net.TrafficStats.TEMPLATE_MOBILE_ALL;
-import static android.net.TrafficStats.isNetworkTemplateMobile;
+import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
+import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
+import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -55,19 +58,25 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkState;
import android.net.NetworkStats;
+import android.net.NetworkTemplate;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.INetworkManagementService;
import android.os.IPowerManager;
+import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
@@ -84,9 +93,9 @@
import com.android.internal.R;
import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.Objects;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -103,6 +112,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import libcore.io.IoUtils;
@@ -143,10 +154,14 @@
private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
+ private static final int MSG_RULES_CHANGED = 0x1;
+ private static final int MSG_METERED_IFACES_CHANGED = 0x2;
+
private final Context mContext;
private final IActivityManager mActivityManager;
private final IPowerManager mPowerManager;
private final INetworkStatsService mNetworkStats;
+ private final INetworkManagementService mNetworkManagement;
private final TrustedTime mTime;
private IConnectivityManager mConnManager;
@@ -155,6 +170,7 @@
private final Object mRulesLock = new Object();
private boolean mScreenOn;
+ private boolean mBackgroundData;
/** Current policy for network templates. */
private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
@@ -164,6 +180,9 @@
/** Current derived network rules for each UID. */
private SparseIntArray mUidRules = new SparseIntArray();
+ /** Set of ifaces that are metered. */
+ private HashSet<String> mMeteredIfaces = Sets.newHashSet();
+
/** Foreground at both UID and PID granularity. */
private SparseBooleanArray mUidForeground = new SparseBooleanArray();
private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
@@ -180,11 +199,14 @@
// TODO: keep whitelist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs.
+ // TODO: watch for package added broadcast to catch new UIDs.
+
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats) {
+ IPowerManager powerManager, INetworkStatsService networkStats,
+ INetworkManagementService networkManagement) {
// TODO: move to using cached NtpTrustedTime
- this(context, activityManager, powerManager, networkStats, new NtpTrustedTime(),
- getSystemDir());
+ this(context, activityManager, powerManager, networkStats, networkManagement,
+ new NtpTrustedTime(), getSystemDir());
}
private static File getSystemDir() {
@@ -192,17 +214,19 @@
}
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
- IPowerManager powerManager, INetworkStatsService networkStats, TrustedTime time,
- File systemDir) {
+ IPowerManager powerManager, INetworkStatsService networkStats,
+ INetworkManagementService networkManagement,
+ TrustedTime time, File systemDir) {
mContext = checkNotNull(context, "missing context");
mActivityManager = checkNotNull(activityManager, "missing activityManager");
mPowerManager = checkNotNull(powerManager, "missing powerManager");
mNetworkStats = checkNotNull(networkStats, "missing networkStats");
+ mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement");
mTime = checkNotNull(time, "missing TrustedTime");
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
+ mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
}
@@ -223,6 +247,7 @@
}
updateScreenOn();
+ updateBackgroundData(true);
try {
mActivityManager.registerProcessObserver(mProcessObserver);
@@ -241,15 +266,22 @@
mContext.registerReceiver(mScreenReceiver, screenFilter);
// watch for network interfaces to be claimed
- final IntentFilter ifaceFilter = new IntentFilter();
- ifaceFilter.addAction(CONNECTIVITY_ACTION);
- mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
+ final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
- // listen for warning polling events; currently dispatched by
+ // listen for uid removal to clean policy
+ final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
+ mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
+
+ // listen for stats update events
final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
mContext.registerReceiver(
mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
+ // listen for changes to background data flag
+ final IntentFilter bgFilter = new IntentFilter(ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+ mContext.registerReceiver(mBgReceiver, bgFilter, CONNECTIVITY_INTERNAL, mHandler);
+
}
private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@@ -258,9 +290,6 @@
// only someone like AMS should only be calling us
mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
- // skip when UID couldn't have any policy
- if (!isUidValidForPolicy(mContext, uid)) return;
-
synchronized (mRulesLock) {
// because a uid can have multiple pids running inside, we need to
// remember all pid states and summarize foreground at uid level.
@@ -281,9 +310,6 @@
// only someone like AMS should only be calling us
mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
- // skip when UID couldn't have any policy
- if (!isUidValidForPolicy(mContext, uid)) return;
-
synchronized (mRulesLock) {
// clear records and recompute, when they exist
final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
@@ -306,6 +332,21 @@
}
};
+ private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // on background handler thread, and UID_REMOVED is protected
+ // broadcast.
+ final int uid = intent.getIntExtra(EXTRA_UID, 0);
+ synchronized (mRulesLock) {
+ // remove any policy and update rules to clean up
+ mUidPolicy.delete(uid);
+ updateRulesForUidLocked(uid);
+ writePolicyLocked();
+ }
+ }
+ };
+
/**
* Receiver that watches for {@link INetworkStatsService} updates, which we
* use to check against {@link NetworkPolicy#warningBytes}.
@@ -323,6 +364,22 @@
};
/**
+ * Receiver that watches for
+ * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
+ */
+ private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // on background handler thread, and verified CONNECTIVITY_INTERNAL
+ // permission above.
+
+ synchronized (mRulesLock) {
+ updateBackgroundData(false);
+ }
+ }
+ };
+
+ /**
* Check {@link NetworkPolicy} against current {@link INetworkStatsService}
* to show visible notifications as needed.
*/
@@ -348,10 +405,10 @@
final long total;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
- start, end, policy.networkTemplate, policy.subscriberId);
+ policy.template, start, end);
total = stats.rx[0] + stats.tx[0];
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate);
+ Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
@@ -375,8 +432,7 @@
* notification of a specific type, like {@link #TYPE_LIMIT}.
*/
private String buildNotificationTag(NetworkPolicy policy, int type) {
- // TODO: consider splicing subscriberId hash into mix
- return TAG + ":" + policy.networkTemplate + ":" + type;
+ return TAG + ":" + policy.template.hashCode() + ":" + type;
}
/**
@@ -403,7 +459,7 @@
final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.networkTemplate);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
@@ -411,11 +467,11 @@
case TYPE_LIMIT: {
final String title;
final String body = res.getString(R.string.data_usage_limit_body);
- switch (policy.networkTemplate) {
- case TEMPLATE_MOBILE_3G_LOWER:
+ switch (policy.template.getMatchRule()) {
+ case MATCH_MOBILE_3G_LOWER:
title = res.getString(R.string.data_usage_3g_limit_title);
break;
- case TEMPLATE_MOBILE_4G:
+ case MATCH_MOBILE_4G:
title = res.getString(R.string.data_usage_4g_limit_title);
break;
default:
@@ -430,7 +486,7 @@
final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.networkTemplate);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
@@ -468,7 +524,7 @@
* Receiver that watches for {@link IConnectivityManager} to claim network
* interfaces. Used to apply {@link NetworkPolicy} to matching networks.
*/
- private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
@@ -516,7 +572,7 @@
// collect all active ifaces that match this template
ifaceList.clear();
for (NetworkIdentity ident : networks.keySet()) {
- if (ident.matchesTemplate(policy.networkTemplate, policy.subscriberId)) {
+ if (policy.template.matches(ident)) {
final String iface = networks.get(ident);
ifaceList.add(iface);
}
@@ -536,6 +592,8 @@
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
+ final HashSet<String> newMeteredIfaces = Sets.newHashSet();
+
// apply each policy that we found ifaces for; compute remaining data
// based on current cycle and historical stats, and push to kernel.
for (NetworkPolicy policy : rules.keySet()) {
@@ -547,11 +605,10 @@
final NetworkStats stats;
final long total;
try {
- stats = mNetworkStats.getSummaryForNetwork(
- start, end, policy.networkTemplate, policy.subscriberId);
+ stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end);
total = stats.rx[0] + stats.tx[0];
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading summary for template " + policy.networkTemplate);
+ Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
@@ -565,9 +622,30 @@
if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
// remaining "quota" is based on usage in current cycle
final long quota = Math.max(0, policy.limitBytes - total);
- //kernelSetIfacesQuota(ifaces, quota);
+
+ if (ifaces.length > 1) {
+ // TODO: switch to shared quota once NMS supports
+ Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
+ }
+
+ for (String iface : ifaces) {
+ removeInterfaceQuota(iface);
+ setInterfaceQuota(iface, quota);
+ newMeteredIfaces.add(iface);
+ }
}
}
+
+ // remove quota on any trailing interfaces
+ for (String iface : mMeteredIfaces) {
+ if (!newMeteredIfaces.contains(iface)) {
+ removeInterfaceQuota(iface);
+ }
+ }
+ mMeteredIfaces = newMeteredIfaces;
+
+ final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
+ mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
}
/**
@@ -577,12 +655,13 @@
private void ensureActiveMobilePolicyLocked() {
if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
final String subscriberId = getActiveSubscriberId();
+ final NetworkIdentity probeIdent = new NetworkIdentity(
+ TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
for (NetworkPolicy policy : mNetworkPolicy) {
- if (isNetworkTemplateMobile(policy.networkTemplate)
- && Objects.equal(subscriberId, policy.subscriberId)) {
+ if (policy.template.matches(probeIdent)) {
mobileDefined = true;
}
}
@@ -598,8 +677,9 @@
time.setToNow();
final int cycleDay = time.monthDay;
- mNetworkPolicy.add(new NetworkPolicy(
- TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
+ final NetworkTemplate template = new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
+ mNetworkPolicy.add(
+ new NetworkPolicy(template, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
writePolicyLocked();
}
}
@@ -632,8 +712,10 @@
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
- mNetworkPolicy.add(new NetworkPolicy(
- networkTemplate, subscriberId, cycleDay, warningBytes, limitBytes));
+ final NetworkTemplate template = new NetworkTemplate(
+ networkTemplate, subscriberId);
+ mNetworkPolicy.add(
+ new NetworkPolicy(template, cycleDay, warningBytes, limitBytes));
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
@@ -675,10 +757,13 @@
// write all known network policies
for (NetworkPolicy policy : mNetworkPolicy) {
+ final NetworkTemplate template = policy.template;
+
out.startTag(null, TAG_NETWORK_POLICY);
- writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, policy.networkTemplate);
- if (policy.subscriberId != null) {
- out.attribute(null, ATTR_SUBSCRIBER_ID, policy.subscriberId);
+ writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
+ final String subscriberId = template.getSubscriberId();
+ if (subscriberId != null) {
+ out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
}
writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
@@ -752,20 +837,7 @@
mListeners.register(listener);
- synchronized (mRulesLock) {
- // dispatch any existing rules to new listeners
- final int size = mUidRules.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidRules.keyAt(i);
- final int uidRules = mUidRules.valueAt(i);
- if (uidRules != RULE_ALLOW_ALL) {
- try {
- listener.onRulesChanged(uid, uidRules);
- } catch (RemoteException e) {
- }
- }
- }
- }
+ // TODO: consider dispatching existing rules to new listeners
}
@Override
@@ -899,6 +971,21 @@
}
}
+ private void updateBackgroundData(boolean systemReady) {
+ synchronized (mRulesLock) {
+ try {
+ mBackgroundData = mConnManager.getBackgroundDataSetting();
+ } catch (RemoteException e) {
+ }
+ if (systemReady && mBackgroundData) {
+ // typical behavior of background enabled during systemReady;
+ // no need to clear rules for all UIDs.
+ } else {
+ updateRulesForBackgroundDataLocked();
+ }
+ }
+ }
+
/**
* Update rules that might be changed by {@link #mScreenOn} value.
*/
@@ -913,17 +1000,46 @@
}
}
- private void updateRulesForUidLocked(int uid) {
- if (!isUidValidForPolicy(mContext, uid)) return;
+ /**
+ * Update rules that might be changed by {@link #mBackgroundData} value.
+ */
+ private void updateRulesForBackgroundDataLocked() {
+ // update rules for all installed applications
+ final PackageManager pm = mContext.getPackageManager();
+ final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
+ for (ApplicationInfo app : apps) {
+ updateRulesForUidLocked(app.uid);
+ }
+ // and catch system UIDs
+ // TODO: keep in sync with android_filesystem_config.h
+ for (int uid = 1000; uid <= 1025; uid++) {
+ updateRulesForUidLocked(uid);
+ }
+ for (int uid = 2000; uid <= 2002; uid++) {
+ updateRulesForUidLocked(uid);
+ }
+ for (int uid = 3000; uid <= 3007; uid++) {
+ updateRulesForUidLocked(uid);
+ }
+ for (int uid = 9998; uid <= 9999; uid++) {
+ updateRulesForUidLocked(uid);
+ }
+ }
+
+ private void updateRulesForUidLocked(int uid) {
final int uidPolicy = getUidPolicy(uid);
final boolean uidForeground = isUidForeground(uid);
// derive active rules based on policy and active state
int uidRules = RULE_ALLOW_ALL;
- if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
- // uid in background, and policy says to block paid data
- uidRules = RULE_REJECT_PAID;
+ if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
+ // uid in background, and policy says to block metered data
+ uidRules = RULE_REJECT_METERED;
+ }
+ if (!uidForeground && !mBackgroundData) {
+ // uid in background, and global background disabled
+ uidRules = RULE_REJECT_METERED;
}
// TODO: only dispatch when rules actually change
@@ -931,21 +1047,83 @@
// record rule locally to dispatch to new listeners
mUidRules.put(uid, uidRules);
- final boolean rejectPaid = (uidRules & RULE_REJECT_PAID) != 0;
- //kernelSetUidRejectPaid(uid, rejectPaid);
+ final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
+ setUidNetworkRules(uid, rejectMetered);
// dispatch changed rule to existing listeners
- final int length = mListeners.beginBroadcast();
- for (int i = 0; i < length; i++) {
- final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
- if (listener != null) {
- try {
- listener.onRulesChanged(uid, uidRules);
- } catch (RemoteException e) {
+ mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
+ }
+
+ private Handler.Callback mHandlerCallback = new Handler.Callback() {
+ /** {@inheritDoc} */
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_RULES_CHANGED: {
+ final int uid = msg.arg1;
+ final int uidRules = msg.arg2;
+ final int length = mListeners.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+ if (listener != null) {
+ try {
+ listener.onUidRulesChanged(uid, uidRules);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mListeners.finishBroadcast();
+ return true;
+ }
+ case MSG_METERED_IFACES_CHANGED: {
+ final String[] meteredIfaces = (String[]) msg.obj;
+ final int length = mListeners.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+ if (listener != null) {
+ try {
+ listener.onMeteredIfacesChanged(meteredIfaces);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mListeners.finishBroadcast();
+ return true;
+ }
+ default: {
+ return false;
}
}
}
- mListeners.finishBroadcast();
+ };
+
+ private void setInterfaceQuota(String iface, long quota) {
+ try {
+ mNetworkManagement.setInterfaceQuota(iface, quota);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem setting interface quota", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem setting interface quota", e);
+ }
+ }
+
+ private void removeInterfaceQuota(String iface) {
+ try {
+ mNetworkManagement.removeInterfaceQuota(iface);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem removing interface quota", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem removing interface quota", e);
+ }
+ }
+
+ private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
+ try {
+ mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem setting uid rules", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem setting uid rules", e);
+ }
}
private String getActiveSubscriberId() {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index f762123..7610a11 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -19,14 +19,20 @@
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
-import static android.Manifest.permission.SHUTDOWN;
+import static android.content.Intent.ACTION_SHUTDOWN;
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.TrafficStats.UID_REMOVED;
+import static android.provider.Settings.Secure.NETSTATS_ENABLED;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
+import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
@@ -45,10 +51,12 @@
import android.content.pm.ApplicationInfo;
import android.net.IConnectivityManager;
import android.net.INetworkStatsService;
+import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -57,14 +65,15 @@
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import android.util.LongSparseArray;
import android.util.NtpTrustedTime;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TrustedTime;
import com.android.internal.os.AtomicFile;
-import com.google.android.collect.Lists;
+import com.android.server.NativeDaemonConnectorException;
import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -76,9 +85,9 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ProtocolException;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import libcore.io.IoUtils;
@@ -93,7 +102,10 @@
/** File header magic number: "ANET" */
private static final int FILE_MAGIC = 0x414E4554;
- private static final int VERSION_CURRENT = 1;
+ private static final int VERSION_NETWORK_INIT = 1;
+ private static final int VERSION_UID_INIT = 1;
+ private static final int VERSION_UID_WITH_IDENT = 2;
+ private static final int VERSION_UID_WITH_TAG = 3;
private final Context mContext;
private final INetworkManagementService mNetworkManager;
@@ -112,6 +124,7 @@
private PendingIntent mPollIntent;
// TODO: listen for kernel push events through netd instead of polling
+ // TODO: trim empty history objects entirely
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
@@ -121,32 +134,34 @@
* Settings that can be changed externally.
*/
public interface NetworkStatsSettings {
+ public boolean getEnabled();
public long getPollInterval();
public long getPersistThreshold();
public long getNetworkBucketDuration();
public long getNetworkMaxHistory();
public long getUidBucketDuration();
public long getUidMaxHistory();
+ public long getTagMaxHistory();
public long getTimeCacheMaxAge();
}
private final Object mStatsLock = new Object();
- /** Set of active ifaces during this boot. */
- private HashMap<String, InterfaceIdentity> mActiveIface = Maps.newHashMap();
-
- /** Set of historical stats for known ifaces. */
- private HashMap<InterfaceIdentity, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
+ /** Set of currently active ifaces. */
+ private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
+ /** Set of historical stats for known networks. */
+ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
/** Set of historical stats for known UIDs. */
- private SparseArray<NetworkStatsHistory> mUidStats = new SparseArray<NetworkStatsHistory>();
+ private HashMap<NetworkIdentitySet, LongSparseArray<NetworkStatsHistory>> mUidStats =
+ Maps.newHashMap();
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
- private NetworkStats mLastNetworkPoll;
- private NetworkStats mLastNetworkPersist;
+ private NetworkStats mLastNetworkSnapshot;
+ private NetworkStats mLastPersistNetworkSnapshot;
- private NetworkStats mLastUidPoll;
+ private NetworkStats mLastUidSnapshot;
private final HandlerThread mHandlerThread;
private final Handler mHandler;
@@ -192,6 +207,20 @@
}
public void systemReady() {
+ if (mSettings.getEnabled()) {
+ try {
+ // enable low-level bandwidth stats and control
+ // TODO: consider shipping with this enabled by default
+ mNetworkManager.setBandwidthControlEnabled(true);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem talking to netd while enabling bandwidth controls", e);
+ } catch (NativeDaemonConnectorException ndce) {
+ Slog.e(TAG, "problem enabling bandwidth controls", ndce);
+ }
+ } else {
+ Slog.w(TAG, "detailed network stats disabled");
+ }
+
synchronized (mStatsLock) {
// read historical network stats from disk, since policy service
// might need them right away. we delay loading detailed UID stats
@@ -200,17 +229,20 @@
}
// watch for network interfaces to be claimed
- final IntentFilter ifaceFilter = new IntentFilter();
- ifaceFilter.addAction(CONNECTIVITY_ACTION);
- mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
+ final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
+ // listen for uid removal to clean stats
+ final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
+ mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
+
// persist stats during clean shutdown
- final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
- mContext.registerReceiver(mShutdownReceiver, shutdownFilter, SHUTDOWN, null);
+ final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
+ mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
try {
registerPollAlarmLocked();
@@ -220,12 +252,15 @@
}
private void shutdownLocked() {
- mContext.unregisterReceiver(mIfaceReceiver);
+ mContext.unregisterReceiver(mConnReceiver);
mContext.unregisterReceiver(mPollReceiver);
+ mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
writeNetworkStatsLocked();
- writeUidStatsLocked();
+ if (mUidStatsLoaded) {
+ writeUidStatsLocked();
+ }
mNetworkStats.clear();
mUidStats.clear();
mUidStatsLoaded = false;
@@ -249,18 +284,19 @@
}
@Override
- public NetworkStatsHistory getHistoryForNetwork(int networkTemplate) {
+ public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
// combine all interfaces that match template
- final String subscriberId = getActiveSubscriberId();
final NetworkStatsHistory combined = new NetworkStatsHistory(
mSettings.getNetworkBucketDuration(), estimateNetworkBuckets());
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
- combined.recordEntireHistory(history);
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
+ if (history != null) {
+ combined.recordEntireHistory(history);
+ }
}
}
return combined;
@@ -268,19 +304,30 @@
}
@Override
- public NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate) {
+ public NetworkStatsHistory getHistoryForUid(NetworkTemplate template, int uid, int tag) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
- // TODO: combine based on template, if we store that granularity
ensureUidStatsLoadedLocked();
- return mUidStats.get(uid);
+ final long packed = packUidAndTag(uid, tag);
+
+ // combine all interfaces that match template
+ final NetworkStatsHistory combined = new NetworkStatsHistory(
+ mSettings.getUidBucketDuration(), estimateUidBuckets());
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mUidStats.get(ident).get(packed);
+ if (history != null) {
+ combined.recordEntireHistory(history);
+ }
+ }
+ }
+ return combined;
}
}
@Override
- public NetworkStats getSummaryForNetwork(
- long start, long end, int networkTemplate, String subscriberId) {
+ public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
synchronized (mStatsLock) {
@@ -289,9 +336,9 @@
long[] networkTotal = new long[2];
// combine total from all interfaces that match template
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory history = mNetworkStats.get(ident);
- if (ident.matchesTemplate(networkTemplate, subscriberId)) {
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
networkTotal = history.getTotalData(start, end, networkTotal);
rx += networkTotal[0];
tx += networkTotal[1];
@@ -299,30 +346,45 @@
}
final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addEntry(IFACE_ALL, UID_ALL, rx, tx);
+ stats.addEntry(IFACE_ALL, UID_ALL, TAG_NONE, rx, tx);
return stats;
}
}
@Override
- public NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate) {
+ public NetworkStats getSummaryForAllUid(
+ NetworkTemplate template, long start, long end, boolean includeTags) {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
- // TODO: apply networktemplate once granular uid stats are stored.
-
synchronized (mStatsLock) {
ensureUidStatsLoadedLocked();
- final int size = mUidStats.size();
- final NetworkStats stats = new NetworkStats(end - start, size);
-
+ final NetworkStats stats = new NetworkStats(end - start, 24);
long[] total = new long[2];
- for (int i = 0; i < size; i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory history = mUidStats.valueAt(i);
- total = history.getTotalData(start, end, total);
- stats.addEntry(IFACE_ALL, uid, total[0], total[1]);
+
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ if (templateMatches(template, ident)) {
+ final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ for (int i = 0; i < uidStats.size(); i++) {
+ final long packed = uidStats.keyAt(i);
+ final int uid = unpackUid(packed);
+ final int tag = unpackTag(packed);
+
+ // always include summary under TAG_NONE, and include
+ // other tags when requested.
+ if (tag == TAG_NONE || includeTags) {
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ total = history.getTotalData(start, end, total);
+ final long rx = total[0];
+ final long tx = total[1];
+ if (rx > 0 || tx > 0) {
+ stats.combineEntry(IFACE_ALL, uid, tag, rx, tx);
+ }
+ }
+ }
+ }
}
+
return stats;
}
}
@@ -332,7 +394,7 @@
* interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
* with mobile interfaces.
*/
- private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
@@ -350,7 +412,19 @@
// permission above.
synchronized (mStatsLock) {
// TODO: acquire wakelock while performing poll
- performPollLocked(true);
+ performPollLocked(true, false);
+ }
+ }
+ };
+
+ private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // on background handler thread, and UID_REMOVED is protected
+ // broadcast.
+ final int uid = intent.getIntExtra(EXTRA_UID, 0);
+ synchronized (mStatsLock) {
+ removeUidLocked(uid);
}
}
};
@@ -358,7 +432,7 @@
private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- // verified SHUTDOWN permission above.
+ // SHUTDOWN is protected broadcast.
synchronized (mStatsLock) {
shutdownLocked();
}
@@ -369,7 +443,7 @@
* Inspect all current {@link NetworkState} to derive mapping from {@code
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
* are active on a single {@code iface}, they are combined under a single
- * {@link InterfaceIdentity}.
+ * {@link NetworkIdentitySet}.
*/
private void updateIfacesLocked() {
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -377,7 +451,7 @@
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
// the updated network.
- performPollLocked(false);
+ performPollLocked(false, false);
final NetworkState[] states;
try {
@@ -388,13 +462,19 @@
}
// rebuild active interfaces based on connected networks
- mActiveIface.clear();
+ mActiveIfaces.clear();
for (NetworkState state : states) {
if (state.networkInfo.isConnected()) {
// collect networks under their parent interfaces
final String iface = state.linkProperties.getInterfaceName();
- final InterfaceIdentity ident = findOrCreateInterfaceLocked(iface);
+
+ NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ if (ident == null) {
+ ident = new NetworkIdentitySet();
+ mActiveIfaces.put(iface, ident);
+ }
+
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
}
}
@@ -407,7 +487,7 @@
* @param detailedPoll Indicate if detailed UID stats should be collected
* during this poll operation.
*/
- private void performPollLocked(boolean detailedPoll) {
+ private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
if (LOGV) Slog.v(TAG, "performPollLocked()");
// try refreshing time source when stale
@@ -419,31 +499,37 @@
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
- final NetworkStats networkStats;
- final NetworkStats uidStats;
+ final NetworkStats networkSnapshot;
+ final NetworkStats uidSnapshot;
try {
- networkStats = mNetworkManager.getNetworkStatsSummary();
- uidStats = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
+ networkSnapshot = mNetworkManager.getNetworkStatsSummary();
+ uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "problem reading network stats: " + e);
+ return;
} catch (RemoteException e) {
- Slog.w(TAG, "problem reading network stats");
+ Slog.w(TAG, "problem reading network stats: " + e);
return;
}
- performNetworkPollLocked(networkStats, currentTime);
+ performNetworkPollLocked(networkSnapshot, currentTime);
if (detailedPoll) {
- performUidPollLocked(uidStats, currentTime);
+ performUidPollLocked(uidSnapshot, currentTime);
}
// decide if enough has changed to trigger persist
- final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, networkStats);
+ final NetworkStats persistDelta = computeStatsDelta(
+ mLastPersistNetworkSnapshot, networkSnapshot);
final long persistThreshold = mSettings.getPersistThreshold();
for (String iface : persistDelta.getUniqueIfaces()) {
- final int index = persistDelta.findIndex(iface, UID_ALL);
- if (persistDelta.rx[index] > persistThreshold
+ final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
+ if (forcePersist || persistDelta.rx[index] > persistThreshold
|| persistDelta.tx[index] > persistThreshold) {
writeNetworkStatsLocked();
- writeUidStatsLocked();
- mLastNetworkPersist = networkStats;
+ if (mUidStatsLoaded) {
+ writeUidStatsLocked();
+ }
+ mLastPersistNetworkSnapshot = networkSnapshot;
break;
}
}
@@ -457,28 +543,33 @@
/**
* Update {@link #mNetworkStats} historical usage.
*/
- private void performNetworkPollLocked(NetworkStats networkStats, long currentTime) {
- final ArrayList<String> unknownIface = Lists.newArrayList();
+ private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
+ final HashSet<String> unknownIface = Sets.newHashSet();
- final NetworkStats delta = computeStatsDelta(mLastNetworkPoll, networkStats);
+ final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot);
final long timeStart = currentTime - delta.elapsedRealtime;
- final long maxHistory = mSettings.getNetworkMaxHistory();
- for (String iface : delta.getUniqueIfaces()) {
- final InterfaceIdentity ident = mActiveIface.get(iface);
+ for (int i = 0; i < delta.size; i++) {
+ final String iface = delta.iface[i];
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
if (ident == null) {
unknownIface.add(iface);
continue;
}
- final int index = delta.findIndex(iface, UID_ALL);
- final long rx = delta.rx[index];
- final long tx = delta.tx[index];
+ final long rx = delta.rx[i];
+ final long tx = delta.tx[i];
- final NetworkStatsHistory history = findOrCreateNetworkLocked(ident);
+ final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
history.recordData(timeStart, currentTime, rx, tx);
+ }
+
+ // trim any history beyond max
+ final long maxHistory = mSettings.getNetworkMaxHistory();
+ for (NetworkStatsHistory history : mNetworkStats.values()) {
history.removeBucketsBefore(currentTime - maxHistory);
}
- mLastNetworkPoll = networkStats;
+
+ mLastNetworkSnapshot = networkSnapshot;
if (LOGD && unknownIface.size() > 0) {
Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
@@ -488,32 +579,84 @@
/**
* Update {@link #mUidStats} historical usage.
*/
- private void performUidPollLocked(NetworkStats uidStats, long currentTime) {
+ private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
ensureUidStatsLoadedLocked();
- final NetworkStats delta = computeStatsDelta(mLastUidPoll, uidStats);
+ final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot);
final long timeStart = currentTime - delta.elapsedRealtime;
- final long maxHistory = mSettings.getUidMaxHistory();
- for (int uid : delta.getUniqueUids()) {
- // TODO: traverse all ifaces once surfaced in stats
- final int index = delta.findIndex(IFACE_ALL, uid);
- if (index != -1) {
- final long rx = delta.rx[index];
- final long tx = delta.tx[index];
- final NetworkStatsHistory history = findOrCreateUidLocked(uid);
- history.recordData(timeStart, currentTime, rx, tx);
- history.removeBucketsBefore(currentTime - maxHistory);
+ for (int i = 0; i < delta.size; i++) {
+ final String iface = delta.iface[i];
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
+ if (ident == null) {
+ continue;
+ }
+
+ final int uid = delta.uid[i];
+ final int tag = delta.tag[i];
+ final long rx = delta.rx[i];
+ final long tx = delta.tx[i];
+
+ final NetworkStatsHistory history = findOrCreateUidStatsLocked(ident, uid, tag);
+ history.recordData(timeStart, currentTime, rx, tx);
+ }
+
+ // trim any history beyond max
+ final long maxUidHistory = mSettings.getUidMaxHistory();
+ final long maxTagHistory = mSettings.getTagMaxHistory();
+ for (LongSparseArray<NetworkStatsHistory> uidStats : mUidStats.values()) {
+ for (int i = 0; i < uidStats.size(); i++) {
+ final long packed = uidStats.keyAt(i);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+
+ // detailed tags are trimmed sooner than summary in TAG_NONE
+ if (unpackTag(packed) == TAG_NONE) {
+ history.removeBucketsBefore(currentTime - maxUidHistory);
+ } else {
+ history.removeBucketsBefore(currentTime - maxTagHistory);
+ }
}
}
- mLastUidPoll = uidStats;
+
+ mLastUidSnapshot = uidSnapshot;
}
- private NetworkStatsHistory findOrCreateNetworkLocked(InterfaceIdentity ident) {
- final long bucketDuration = mSettings.getNetworkBucketDuration();
+ /**
+ * Clean up {@link #mUidStats} after UID is removed.
+ */
+ private void removeUidLocked(int uid) {
+ ensureUidStatsLoadedLocked();
+
+ // migrate all UID stats into special "removed" bucket
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ for (int i = 0; i < uidStats.size(); i++) {
+ final long packed = uidStats.keyAt(i);
+ if (unpackUid(packed) == uid) {
+ // only migrate combined TAG_NONE history
+ if (unpackTag(packed) == TAG_NONE) {
+ final NetworkStatsHistory uidHistory = uidStats.valueAt(i);
+ final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
+ ident, UID_REMOVED, TAG_NONE);
+ removedHistory.recordEntireHistory(uidHistory);
+ }
+ uidStats.remove(packed);
+ }
+ }
+ }
+
+ // TODO: push kernel event to wipe stats for UID, otherwise we risk
+ // picking them up again during next poll.
+
+ // since this was radical rewrite, push to disk
+ writeUidStatsLocked();
+ }
+
+ private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
final NetworkStatsHistory existing = mNetworkStats.get(ident);
// update when no existing, or when bucket duration changed
+ final long bucketDuration = mSettings.getNetworkBucketDuration();
NetworkStatsHistory updated = null;
if (existing == null) {
updated = new NetworkStatsHistory(bucketDuration, 10);
@@ -531,11 +674,21 @@
}
}
- private NetworkStatsHistory findOrCreateUidLocked(int uid) {
- final long bucketDuration = mSettings.getUidBucketDuration();
- final NetworkStatsHistory existing = mUidStats.get(uid);
+ private NetworkStatsHistory findOrCreateUidStatsLocked(
+ NetworkIdentitySet ident, int uid, int tag) {
+ ensureUidStatsLoadedLocked();
+
+ LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ if (uidStats == null) {
+ uidStats = new LongSparseArray<NetworkStatsHistory>();
+ mUidStats.put(ident, uidStats);
+ }
+
+ final long packed = packUidAndTag(uid, tag);
+ final NetworkStatsHistory existing = uidStats.get(packed);
// update when no existing, or when bucket duration changed
+ final long bucketDuration = mSettings.getUidBucketDuration();
NetworkStatsHistory updated = null;
if (existing == null) {
updated = new NetworkStatsHistory(bucketDuration, 10);
@@ -546,22 +699,13 @@
}
if (updated != null) {
- mUidStats.put(uid, updated);
+ uidStats.put(packed, updated);
return updated;
} else {
return existing;
}
}
- private InterfaceIdentity findOrCreateInterfaceLocked(String iface) {
- InterfaceIdentity ident = mActiveIface.get(iface);
- if (ident == null) {
- ident = new InterfaceIdentity();
- mActiveIface.put(iface, ident);
- }
- return ident;
- }
-
private void readNetworkStatsLocked() {
if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
@@ -581,15 +725,12 @@
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
- // file format is pairs of interfaces and stats:
- // network := size *(InterfaceIdentity NetworkStatsHistory)
-
+ case VERSION_NETWORK_INIT: {
+ // network := size *(NetworkIdentitySet NetworkStatsHistory)
final int size = in.readInt();
for (int i = 0; i < size; i++) {
- final InterfaceIdentity ident = new InterfaceIdentity(in);
+ final NetworkIdentitySet ident = new NetworkIdentitySet(in);
final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
mNetworkStats.put(ident, history);
}
break;
@@ -633,16 +774,39 @@
final int version = in.readInt();
switch (version) {
- case VERSION_CURRENT: {
- // file format is pairs of UIDs and stats:
+ case VERSION_UID_INIT: {
// uid := size *(UID NetworkStatsHistory)
- final int size = in.readInt();
- for (int i = 0; i < size; i++) {
- final int uid = in.readInt();
- final NetworkStatsHistory history = new NetworkStatsHistory(in);
+ // drop this data version, since we don't have a good
+ // mapping into NetworkIdentitySet.
+ break;
+ }
+ case VERSION_UID_WITH_IDENT: {
+ // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
- mUidStats.put(uid, history);
+ // drop this data version, since this version only existed
+ // for a short time.
+ break;
+ }
+ case VERSION_UID_WITH_TAG: {
+ // uid := size *(NetworkIdentitySet size *(UID tag NetworkStatsHistory))
+ final int ifaceSize = in.readInt();
+ for (int i = 0; i < ifaceSize; i++) {
+ final NetworkIdentitySet ident = new NetworkIdentitySet(in);
+
+ final int childSize = in.readInt();
+ final LongSparseArray<NetworkStatsHistory> uidStats = new LongSparseArray<
+ NetworkStatsHistory>(childSize);
+ for (int j = 0; j < childSize; j++) {
+ final int uid = in.readInt();
+ final int tag = in.readInt();
+ final long packed = packUidAndTag(uid, tag);
+
+ final NetworkStatsHistory history = new NetworkStatsHistory(in);
+ uidStats.put(packed, history);
+ }
+
+ mUidStats.put(ident, uidStats);
}
break;
}
@@ -670,10 +834,10 @@
final DataOutputStream out = new DataOutputStream(fos);
out.writeInt(FILE_MAGIC);
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_NETWORK_INIT);
out.writeInt(mNetworkStats.size());
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
final NetworkStatsHistory history = mNetworkStats.get(ident);
ident.writeToStream(out);
history.writeToStream(out);
@@ -690,6 +854,11 @@
private void writeUidStatsLocked() {
if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
+ if (!mUidStatsLoaded) {
+ Slog.w(TAG, "asked to write UID stats when not loaded; skipping");
+ return;
+ }
+
// TODO: consider duplicating stats and releasing lock while writing
FileOutputStream fos = null;
@@ -698,16 +867,25 @@
final DataOutputStream out = new DataOutputStream(fos);
out.writeInt(FILE_MAGIC);
- out.writeInt(VERSION_CURRENT);
+ out.writeInt(VERSION_UID_WITH_TAG);
final int size = mUidStats.size();
-
out.writeInt(size);
- for (int i = 0; i < size; i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory history = mUidStats.valueAt(i);
- out.writeInt(uid);
- history.writeToStream(out);
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ ident.writeToStream(out);
+
+ final int childSize = uidStats.size();
+ out.writeInt(childSize);
+ for (int i = 0; i < childSize; i++) {
+ final long packed = uidStats.keyAt(i);
+ final int uid = unpackUid(packed);
+ final int tag = unpackTag(packed);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ out.writeInt(uid);
+ out.writeInt(tag);
+ history.writeToStream(out);
+ }
}
mUidFile.finishWrite(fos);
@@ -736,35 +914,44 @@
}
if (argSet.contains("poll")) {
- performPollLocked(true);
+ performPollLocked(true, true);
pw.println("Forced poll");
return;
}
pw.println("Active interfaces:");
- for (String iface : mActiveIface.keySet()) {
- final InterfaceIdentity ident = mActiveIface.get(iface);
+ for (String iface : mActiveIfaces.keySet()) {
+ final NetworkIdentitySet ident = mActiveIfaces.get(iface);
pw.print(" iface="); pw.print(iface);
pw.print(" ident="); pw.println(ident.toString());
}
pw.println("Known historical stats:");
- for (InterfaceIdentity ident : mNetworkStats.keySet()) {
- final NetworkStatsHistory stats = mNetworkStats.get(ident);
+ for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
+ final NetworkStatsHistory history = mNetworkStats.get(ident);
pw.print(" ident="); pw.println(ident.toString());
- stats.dump(" ", pw);
+ history.dump(" ", pw);
}
if (argSet.contains("detail")) {
// since explicitly requested with argument, we're okay to load
// from disk if not already in memory.
ensureUidStatsLoadedLocked();
- pw.println("Known UID stats:");
- for (int i = 0; i < mUidStats.size(); i++) {
- final int uid = mUidStats.keyAt(i);
- final NetworkStatsHistory stats = mUidStats.valueAt(i);
- pw.print(" UID="); pw.println(uid);
- stats.dump(" ", pw);
+
+ pw.println("Detailed UID stats:");
+ for (NetworkIdentitySet ident : mUidStats.keySet()) {
+ pw.print(" ident="); pw.println(ident.toString());
+
+ final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
+ for (int i = 0; i < uidStats.size(); i++) {
+ final long packed = uidStats.keyAt(i);
+ final int uid = unpackUid(packed);
+ final int tag = unpackTag(packed);
+ final NetworkStatsHistory history = uidStats.valueAt(i);
+ pw.print(" UID="); pw.print(uid);
+ pw.print(" tag="); pw.println(tag);
+ history.dump(" ", pw);
+ }
}
}
}
@@ -775,27 +962,30 @@
*/
@Deprecated
private void generateRandomLocked() {
- long end = System.currentTimeMillis();
- long start = end - mSettings.getNetworkMaxHistory();
- long rx = 3 * GB_IN_BYTES;
- long tx = 2 * GB_IN_BYTES;
+ long networkEnd = System.currentTimeMillis();
+ long networkStart = networkEnd - mSettings.getNetworkMaxHistory();
+ long networkRx = 3 * GB_IN_BYTES;
+ long networkTx = 2 * GB_IN_BYTES;
+
+ long uidEnd = System.currentTimeMillis();
+ long uidStart = uidEnd - mSettings.getUidMaxHistory();
+ long uidRx = 500 * MB_IN_BYTES;
+ long uidTx = 100 * MB_IN_BYTES;
+
+ final List<ApplicationInfo> installedApps = mContext
+ .getPackageManager().getInstalledApplications(0);
mNetworkStats.clear();
- for (InterfaceIdentity ident : mActiveIface.values()) {
- final NetworkStatsHistory stats = findOrCreateNetworkLocked(ident);
- stats.generateRandom(start, end, rx, tx);
- }
-
- end = System.currentTimeMillis();
- start = end - mSettings.getUidMaxHistory();
- rx = 500 * MB_IN_BYTES;
- tx = 100 * MB_IN_BYTES;
-
mUidStats.clear();
- for (ApplicationInfo info : mContext.getPackageManager().getInstalledApplications(0)) {
- final int uid = info.uid;
- final NetworkStatsHistory stats = findOrCreateUidLocked(uid);
- stats.generateRandom(start, end, rx, tx);
+ for (NetworkIdentitySet ident : mActiveIfaces.values()) {
+ findOrCreateNetworkStatsLocked(ident).generateRandom(
+ networkStart, networkEnd, networkRx, networkTx);
+
+ for (ApplicationInfo info : installedApps) {
+ final int uid = info.uid;
+ findOrCreateUidStatsLocked(ident, uid, TAG_NONE).generateRandom(
+ uidStart, uidEnd, uidRx, uidTx);
+ }
}
}
@@ -811,12 +1001,6 @@
}
}
- private String getActiveSubscriberId() {
- final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- return telephony.getSubscriberId();
- }
-
private int estimateNetworkBuckets() {
return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
}
@@ -829,6 +1013,36 @@
return (int) (existing.bucketCount * existing.bucketDuration / newBucketDuration);
}
+ // @VisibleForTesting
+ public static long packUidAndTag(int uid, int tag) {
+ final long uidLong = uid;
+ final long tagLong = tag;
+ return (uidLong << 32) | (tagLong & 0xFFFFFFFFL);
+ }
+
+ // @VisibleForTesting
+ public static int unpackUid(long packed) {
+ return (int) (packed >> 32);
+ }
+
+ // @VisibleForTesting
+ public static int unpackTag(long packed) {
+ return (int) (packed & 0xFFFFFFFFL);
+ }
+
+ /**
+ * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
+ * in the given {@link NetworkIdentitySet}.
+ */
+ private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
+ for (NetworkIdentity ident : identSet) {
+ if (template.matches(ident)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Default external settings that read from {@link Settings.Secure}.
*/
@@ -844,6 +1058,15 @@
return Settings.Secure.getLong(mResolver, name, def);
}
+ public boolean getEnabled() {
+ if (!new File("/proc/net/xt_qtaguid/ctrl").exists()) {
+ Slog.w(TAG, "kernel does not support bandwidth control");
+ return false;
+ }
+ // TODO: once things stabilize, enable by default.
+ // For now: ./vendor/google/tools/override-gservices secure:netstats_enabled=1
+ return Settings.Secure.getInt(mResolver, NETSTATS_ENABLED, 0) != 0;
+ }
public long getPollInterval() {
return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
}
@@ -862,6 +1085,9 @@
public long getUidMaxHistory() {
return getSecureLong(NETSTATS_UID_MAX_HISTORY, 90 * DAY_IN_MILLIS);
}
+ public long getTagMaxHistory() {
+ return getSecureLong(NETSTATS_TAG_MAX_HISTORY, 30 * DAY_IN_MILLIS);
+ }
public long getTimeCacheMaxAge() {
return DAY_IN_MILLIS;
}
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index d10aa97..11ccd60 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -307,7 +307,7 @@
}
public int getSizeInfo(String pkgName, String apkPath, String fwdLockApkPath,
- PackageStats pStats) {
+ String asecPath, PackageStats pStats) {
StringBuilder builder = new StringBuilder("getsize");
builder.append(' ');
builder.append(pkgName);
@@ -315,17 +315,20 @@
builder.append(apkPath);
builder.append(' ');
builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
+ builder.append(' ');
+ builder.append(asecPath != null ? asecPath : "!");
String s = transaction(builder.toString());
String res[] = s.split(" ");
- if ((res == null) || (res.length != 4)) {
+ if ((res == null) || (res.length != 5)) {
return -1;
}
try {
pStats.codeSize = Long.parseLong(res[1]);
pStats.dataSize = Long.parseLong(res[2]);
pStats.cacheSize = Long.parseLong(res[3]);
+ pStats.externalCodeSize = Long.parseLong(res[4]);
return Integer.parseInt(res[0]);
} catch (NumberFormatException e) {
return -1;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index e1fbe1c..22e2dde 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import com.android.internal.app.IMediaContainerService;
@@ -74,6 +75,7 @@
import android.os.Environment;
import android.os.FileObserver;
import android.os.FileUtils;
+import android.os.FileUtils.FileStatus;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -4886,8 +4888,7 @@
private final IPackageStatsObserver mObserver;
- public MeasureParams(PackageStats stats, boolean success,
- IPackageStatsObserver observer) {
+ public MeasureParams(PackageStats stats, boolean success, IPackageStatsObserver observer) {
mObserver = observer;
mStats = stats;
mSuccess = success;
@@ -5479,6 +5480,17 @@
}
}
+ /**
+ * Extract the MountService "container ID" from the full code path of an
+ * .apk.
+ */
+ static String cidFromCodePath(String fullCodePath) {
+ int eidx = fullCodePath.lastIndexOf("/");
+ String subStr1 = fullCodePath.substring(0, eidx);
+ int sidx = subStr1.lastIndexOf("/");
+ return subStr1.substring(sidx+1, eidx);
+ }
+
class SdInstallArgs extends InstallArgs {
static final String RES_FILE_NAME = "pkg.apk";
@@ -6830,6 +6842,7 @@
}
PackageParser.Package p;
boolean dataOnly = false;
+ String asecPath = null;
synchronized (mPackages) {
p = mPackages.get(packageName);
if(p == null) {
@@ -6841,6 +6854,12 @@
}
p = ps.pkg;
}
+ if (p != null && isExternal(p)) {
+ String secureContainerId = cidFromCodePath(p.applicationInfo.sourceDir);
+ if (secureContainerId != null) {
+ asecPath = PackageHelper.getSdFilesystem(secureContainerId);
+ }
+ }
}
String publicSrcDir = null;
if(!dataOnly) {
@@ -6849,10 +6868,13 @@
Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
return false;
}
- publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
+ if (isForwardLocked(p)) {
+ publicSrcDir = applicationInfo.publicSourceDir;
+ }
}
if (mInstaller != null) {
- int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir, pStats);
+ int res = mInstaller.getSizeInfo(packageName, p.mPath, publicSrcDir,
+ asecPath, pStats);
if (res < 0) {
return false;
} else {
@@ -7048,7 +7070,8 @@
final String packageName, String className, int newState, final int flags) {
if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT
|| newState == COMPONENT_ENABLED_STATE_ENABLED
- || newState == COMPONENT_ENABLED_STATE_DISABLED)) {
+ || newState == COMPONENT_ENABLED_STATE_DISABLED
+ || newState == COMPONENT_ENABLED_STATE_DISABLED_USER)) {
throw new IllegalArgumentException("Invalid new component state: "
+ newState);
}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 2720bf8..5ed7988 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import com.android.internal.util.FastXmlSerializer;
@@ -1912,6 +1913,7 @@
return false;
}
if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED
+ || packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER
|| (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled
&& packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) {
return false;
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index ca8a184..918f1b6 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -19,7 +19,6 @@
import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -33,10 +32,16 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.FileUtils;
import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.provider.Settings;
@@ -46,7 +51,7 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
-import java.io.FileReader;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -55,77 +60,109 @@
* UsbDeviceManager manages USB state in device mode.
*/
public class UsbDeviceManager {
+
private static final String TAG = UsbDeviceManager.class.getSimpleName();
private static final boolean LOG = false;
- private static final String USB_CONNECTED_MATCH =
- "DEVPATH=/devices/virtual/switch/usb_connected";
- private static final String USB_CONFIGURATION_MATCH =
- "DEVPATH=/devices/virtual/switch/usb_configuration";
- private static final String USB_FUNCTIONS_MATCH =
- "DEVPATH=/devices/virtual/usb_composite/";
- private static final String USB_CONNECTED_PATH =
- "/sys/class/switch/usb_connected/state";
- private static final String USB_CONFIGURATION_PATH =
- "/sys/class/switch/usb_configuration/state";
- private static final String USB_COMPOSITE_CLASS_PATH =
- "/sys/class/usb_composite";
+ private static final String USB_STATE_MATCH =
+ "DEVPATH=/devices/virtual/android_usb/android0";
+ private static final String ACCESSORY_START_MATCH =
+ "DEVPATH=/devices/virtual/misc/usb_accessory";
+ private static final String FUNCTIONS_PATH =
+ "/sys/class/android_usb/android0/functions";
+ private static final String STATE_PATH =
+ "/sys/class/android_usb/android0/state";
+ private static final String MASS_STORAGE_FILE_PATH =
+ "/sys/class/android_usb/f_mass_storage/lun/file";
private static final int MSG_UPDATE_STATE = 0;
- private static final int MSG_FUNCTION_ENABLED = 1;
- private static final int MSG_FUNCTION_DISABLED = 2;
+ private static final int MSG_ENABLE_ADB = 1;
+ private static final int MSG_SET_CURRENT_FUNCTION = 2;
+ private static final int MSG_SYSTEM_READY = 3;
// Delay for debouncing USB disconnects.
// We often get rapid connect/disconnect events when enabling USB functions,
// which need debouncing.
private static final int UPDATE_DELAY = 1000;
- // current connected and configuration state
- private int mConnected;
- private int mConfiguration;
-
- // last broadcasted connected and configuration state
- private int mLastConnected = -1;
- private int mLastConfiguration = -1;
-
- // lists of enabled and disabled USB functions
- private final ArrayList<String> mEnabledFunctions = new ArrayList<String>();
-
+ private UsbHandler mHandler;
private boolean mSystemReady;
- private UsbAccessory mCurrentAccessory;
- // USB functions that are enabled by default, to restore after exiting accessory mode
- private final ArrayList<String> mDefaultFunctions = new ArrayList<String>();
-
private final Context mContext;
- ContentResolver mContentResolver;
- private final Object mLock = new Object();
+ private final ContentResolver mContentResolver;
private final UsbSettingsManager mSettingsManager;
private NotificationManager mNotificationManager;
private final boolean mHasUsbAccessory;
- // for adb connected notifications
- private boolean mAdbNotificationShown = false;
+ // for USB connected notification
+ private boolean mUsbNotificationShown;
+ private boolean mUseUsbNotification;
+ private Notification mUsbNotification;
+
+ // for adb connected notification
+ private boolean mAdbNotificationShown;
private Notification mAdbNotification;
private boolean mAdbEnabled;
+
private class AdbSettingsObserver extends ContentObserver {
public AdbSettingsObserver() {
super(null);
}
@Override
public void onChange(boolean selfChange) {
- mAdbEnabled = (Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ADB_ENABLED, 0) > 0);
- // setting this secure property will start or stop adbd
- SystemProperties.set("persist.service.adb.enable", mAdbEnabled ? "1" : "0");
- updateAdbNotification();
+ boolean enable = (Settings.Secure.getInt(mContentResolver,
+ Settings.Secure.ADB_ENABLED, 0) > 0);
+ mHandler.sendMessage(MSG_ENABLE_ADB, enable);
}
}
- private void updateAdbNotification() {
+ private void updateUsbNotification(boolean connected) {
+ if (mNotificationManager == null || !mUseUsbNotification) return;
+ if (connected) {
+ if (!mUsbNotificationShown) {
+ Resources r = mContext.getResources();
+ CharSequence title = r.getText(
+ com.android.internal.R.string.usb_preferences_notification_title);
+ CharSequence message = r.getText(
+ com.android.internal.R.string.usb_preferece_notification_message);
+
+ if (mUsbNotification == null) {
+ mUsbNotification = new Notification();
+ mUsbNotification.icon = com.android.internal.R.drawable.stat_sys_data_usb;
+ mUsbNotification.when = 0;
+ mUsbNotification.flags = Notification.FLAG_ONGOING_EVENT;
+ mUsbNotification.tickerText = title;
+ mUsbNotification.defaults = 0; // please be quiet
+ mUsbNotification.sound = null;
+ mUsbNotification.vibrate = null;
+ }
+
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbPreferenceActivity");
+ PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+ intent, 0);
+
+ mUsbNotification.setLatestEventInfo(mContext, title, message, pi);
+
+ mUsbNotificationShown = true;
+ mNotificationManager.notify(
+ com.android.internal.R.string.usb_preferences_notification_title,
+ mUsbNotification);
+ }
+
+ } else if (mUsbNotificationShown) {
+ mUsbNotificationShown = false;
+ mNotificationManager.cancel(
+ com.android.internal.R.string.usb_preferences_notification_title);
+ }
+ }
+
+ private void updateAdbNotification(boolean adbEnabled) {
if (mNotificationManager == null) return;
- boolean adbEnabled = mAdbEnabled && (mConnected == 1);
if (adbEnabled) {
if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
@@ -173,38 +210,6 @@
}
}
- private final void readCurrentAccessoryLocked() {
- if (mHasUsbAccessory) {
- String[] strings = nativeGetAccessoryStrings();
- if (strings != null) {
- mCurrentAccessory = new UsbAccessory(strings);
- Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
- if (mSystemReady) {
- mSettingsManager.accessoryAttached(mCurrentAccessory);
- }
- } else {
- Log.e(TAG, "nativeGetAccessoryStrings failed");
- }
- }
- }
-
- /*
- * Handles USB function enable/disable events
- */
- private final void functionEnabledLocked(String function, boolean enabled) {
- if (enabled) {
- if (!mEnabledFunctions.contains(function)) {
- mEnabledFunctions.add(function);
- }
-
- if (UsbManager.USB_FUNCTION_ACCESSORY.equals(function)) {
- readCurrentAccessoryLocked();
- }
- } else {
- mEnabledFunctions.remove(function);
- }
- }
-
/*
* Listens for uevent messages from the kernel to monitor the USB state
*/
@@ -215,53 +220,13 @@
Slog.v(TAG, "USB UEVENT: " + event.toString());
}
- synchronized (mLock) {
- String name = event.get("SWITCH_NAME");
- String state = event.get("SWITCH_STATE");
- if (name != null && state != null) {
- try {
- int intState = Integer.parseInt(state);
- if ("usb_connected".equals(name)) {
- mConnected = intState;
- // trigger an Intent broadcast
- if (mSystemReady) {
- // debounce disconnects to avoid problems bringing up USB tethering
- update(mConnected == 0);
- }
- } else if ("usb_configuration".equals(name)) {
- mConfiguration = intState;
- // trigger an Intent broadcast
- if (mSystemReady) {
- update(mConnected == 0);
- }
- }
- } catch (NumberFormatException e) {
- Slog.e(TAG, "Could not parse switch state from event " + event);
- }
- } else {
- String function = event.get("FUNCTION");
- String enabledStr = event.get("ENABLED");
- if (function != null && enabledStr != null) {
- // Note: we do not broadcast a change when a function is enabled or disabled.
- // We just record the state change for the next broadcast.
- int what = ("1".equals(enabledStr) ?
- MSG_FUNCTION_ENABLED : MSG_FUNCTION_DISABLED);
- Message msg = Message.obtain(mHandler, what);
- msg.obj = function;
- mHandler.sendMessage(msg);
- }
- }
- }
- }
- };
-
- private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- // handle accessories attached at boot time
- synchronized (mLock) {
- if (mCurrentAccessory != null) {
- mSettingsManager.accessoryAttached(mCurrentAccessory);
- }
+ String state = event.get("USB_STATE");
+ String accessory = event.get("ACCESSORY");
+ if (state != null) {
+ mHandler.updateState(state);
+ } else if ("START".equals(accessory)) {
+ Slog.d(TAG, "got accessory start");
+ setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false);
}
}
};
@@ -273,229 +238,391 @@
PackageManager pm = mContext.getPackageManager();
mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
- synchronized (mLock) {
- init(); // set initial status
-
- // make sure the ADB_ENABLED setting value matches the secure property value
- mAdbEnabled = "1".equals(SystemProperties.get("persist.service.adb.enable"));
- Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED,
- mAdbEnabled ? 1 : 0);
-
- // register observer to listen for settings changes
- mContentResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
- false, new AdbSettingsObserver());
-
- // Watch for USB configuration changes
- if (mConfiguration >= 0) {
- mUEventObserver.startObserving(USB_CONNECTED_MATCH);
- mUEventObserver.startObserving(USB_CONFIGURATION_MATCH);
- mUEventObserver.startObserving(USB_FUNCTIONS_MATCH);
+ // create a thread for our Handler
+ HandlerThread thread = new HandlerThread("UsbDeviceManager",
+ Process.THREAD_PRIORITY_BACKGROUND) {
+ protected void onLooperPrepared() {
+ mHandler = new UsbHandler();
}
- }
- }
-
- private final void init() {
- char[] buffer = new char[1024];
- boolean inAccessoryMode = false;
-
- // Read initial USB state
- mConfiguration = -1;
- try {
- FileReader file = new FileReader(USB_CONNECTED_PATH);
- int len = file.read(buffer, 0, 1024);
- file.close();
- mConnected = Integer.valueOf((new String(buffer, 0, len)).trim());
-
- file = new FileReader(USB_CONFIGURATION_PATH);
- len = file.read(buffer, 0, 1024);
- file.close();
- mConfiguration = Integer.valueOf((new String(buffer, 0, len)).trim());
-
- } catch (FileNotFoundException e) {
- Slog.i(TAG, "This kernel does not have USB configuration switch support");
- } catch (Exception e) {
- Slog.e(TAG, "" , e);
- }
- if (mConfiguration < 0) {
- // This may happen in the emulator or devices without USB device mode support
- return;
- }
-
- // Read initial list of enabled and disabled functions (device mode)
- try {
- File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles();
- for (int i = 0; i < files.length; i++) {
- File file = new File(files[i], "enable");
- FileReader reader = new FileReader(file);
- int len = reader.read(buffer, 0, 1024);
- reader.close();
- int value = Integer.valueOf((new String(buffer, 0, len)).trim());
- String functionName = files[i].getName();
- if (value == 1) {
- mEnabledFunctions.add(functionName);
- if (UsbManager.USB_FUNCTION_ACCESSORY.equals(functionName)) {
- // The USB accessory driver is on by default, but it might have been
- // enabled before the USB service has initialized.
- inAccessoryMode = true;
- } else if (!UsbManager.USB_FUNCTION_ADB.equals(functionName)) {
- // adb is enabled/disabled automatically by the adbd daemon,
- // so don't treat it as a default function.
- mDefaultFunctions.add(functionName);
- }
- }
- }
- } catch (FileNotFoundException e) {
- Slog.w(TAG, "This kernel does not have USB composite class support");
- } catch (Exception e) {
- Slog.e(TAG, "" , e);
- }
-
- // handle the case where an accessory switched the driver to accessory mode
- // before the framework finished booting
- if (inAccessoryMode) {
- readCurrentAccessoryLocked();
-
- // FIXME - if we booted in accessory mode, then we have no way to figure out
- // which functions are enabled by default.
- // For now, assume that MTP or mass storage are the only possibilities
- if (!mEnabledFunctions.contains(UsbManager.USB_FUNCTION_MTP)) {
- mDefaultFunctions.add(UsbManager.USB_FUNCTION_MTP);
- } else if (!mEnabledFunctions.contains(UsbManager.USB_FUNCTION_MASS_STORAGE)) {
- mDefaultFunctions.add(UsbManager.USB_FUNCTION_MASS_STORAGE);
- }
- }
+ };
+ thread.start();
}
public void systemReady() {
- synchronized (mLock) {
- mNotificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ mSystemReady = true;
- update(false);
- if (mCurrentAccessory != null) {
- Log.d(TAG, "accessoryAttached at systemReady");
- // its still too early to handle accessories, so add a BOOT_COMPLETED receiver
- // to handle this later.
- mContext.registerReceiver(mBootCompletedReceiver,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
- }
- mSystemReady = true;
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ // We do not show the USB notification if the primary volume supports mass storage.
+ // The legacy mass storage UI will be used instead.
+ boolean massStorageSupported = false;
+ StorageManager storageManager = (StorageManager)
+ mContext.getSystemService(Context.STORAGE_SERVICE);
+ StorageVolume[] volumes = storageManager.getVolumeList();
+ if (volumes.length > 0) {
+ massStorageSupported = volumes[0].allowMassStorage();
}
+ mUseUsbNotification = !massStorageSupported;
+
+ // make sure the ADB_ENABLED setting value matches the current state
+ Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+
+ mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
- /*
- * Sends a message to update the USB connected and configured state (device mode).
- * If delayed is true, then we add a small delay in sending the message to debounce
- * the USB connection when enabling USB tethering.
- */
- private final void update(boolean delayed) {
- mHandler.removeMessages(MSG_UPDATE_STATE);
- mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATE, delayed ? UPDATE_DELAY : 0);
- }
-
- /* returns the currently attached USB accessory (device mode) */
- public UsbAccessory getCurrentAccessory() {
- return mCurrentAccessory;
- }
-
- /* opens the currently attached USB accessory (device mode) */
- public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
- synchronized (mLock) {
- if (mCurrentAccessory == null) {
- throw new IllegalArgumentException("no accessory attached");
+ private static String addFunction(String functions, String function) {
+ if (!containsFunction(functions, function)) {
+ if (functions.length() > 0) {
+ functions += ",";
}
- if (!mCurrentAccessory.equals(accessory)) {
- Log.e(TAG, accessory.toString() + " does not match current accessory "
- + mCurrentAccessory);
- throw new IllegalArgumentException("accessory not attached");
- }
- mSettingsManager.checkPermission(mCurrentAccessory);
- return nativeOpenAccessory();
+ functions += function;
}
+ return functions;
}
- /*
- * This handler is for deferred handling of events related to device mode and accessories.
- */
- private final Handler mHandler = new Handler() {
+ private static String removeFunction(String functions, String function) {
+ String[] split = functions.split(",");
+ for (int i = 0; i < split.length; i++) {
+ if (function.equals(split[i])) {
+ split[i] = null;
+ }
+ }
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < split.length; i++) {
+ String s = split[i];
+ if (s != null) {
+ if (builder.length() > 0) {
+ builder.append(",");
+ }
+ builder.append(s);
+ }
+ }
+ return builder.toString();
+ }
- @Override
- public void handleMessage(Message msg) {
- synchronized (mLock) {
- switch (msg.what) {
- case MSG_UPDATE_STATE:
- if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
- updateAdbNotification();
- if (mConnected == 0) {
- if (UsbManager.isFunctionEnabled(
- UsbManager.USB_FUNCTION_ACCESSORY)) {
- // make sure accessory mode is off, and restore default functions
- Log.d(TAG, "exited USB accessory mode");
- if (!UsbManager.setFunctionEnabled
- (UsbManager.USB_FUNCTION_ACCESSORY, false)) {
- Log.e(TAG, "could not disable accessory function");
- }
- int count = mDefaultFunctions.size();
- for (int i = 0; i < count; i++) {
- String function = mDefaultFunctions.get(i);
- if (!UsbManager.setFunctionEnabled(function, true)) {
- Log.e(TAG, "could not reenable function " + function);
- }
- }
+ private static boolean containsFunction(String functions, String function) {
+ int index = functions.indexOf(function);
+ if (index < 0) return false;
+ if (index > 0 && functions.charAt(index - 1) != ',') return false;
+ int charAfter = index + function.length();
+ if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
+ return true;
+ }
- if (mCurrentAccessory != null) {
- mSettingsManager.accessoryDetached(mCurrentAccessory);
- mCurrentAccessory = null;
- }
- }
- }
+ private final class UsbHandler extends Handler {
- final ContentResolver cr = mContext.getContentResolver();
- if (Settings.Secure.getInt(cr,
- Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
- Slog.i(TAG, "Device not provisioned, skipping USB broadcast");
- return;
- }
+ // current USB state
+ private boolean mConnected;
+ private boolean mConfigured;
+ private String mCurrentFunctions;
+ private String mDefaultFunctions;
+ private UsbAccessory mCurrentAccessory;
+ private boolean mDeferAccessoryAttached;
- mLastConnected = mConnected;
- mLastConfiguration = mConfiguration;
+ public UsbHandler() {
+ // Read initial USB state
+ try {
+ mCurrentFunctions = FileUtils.readTextFile(
+ new File(FUNCTIONS_PATH), 0, null).trim();
+ mDefaultFunctions = mCurrentFunctions;
+ String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
+ updateState(state);
- // send a sticky broadcast containing current USB state
- Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(UsbManager.USB_CONNECTED, mConnected != 0);
- intent.putExtra(UsbManager.USB_CONFIGURATION, mConfiguration);
- for (int i = 0; i < mEnabledFunctions.size(); i++) {
- intent.putExtra(mEnabledFunctions.get(i), true);
- }
- mContext.sendStickyBroadcast(intent);
- }
- break;
- case MSG_FUNCTION_ENABLED:
- case MSG_FUNCTION_DISABLED:
- functionEnabledLocked((String)msg.obj, msg.what == MSG_FUNCTION_ENABLED);
- break;
+ mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
+
+ // Upgrade step for previous versions that used persist.service.adb.enable
+ String value = SystemProperties.get("persist.service.adb.enable", "");
+ if (value.length() > 0) {
+ char enable = value.charAt(0);
+ if (enable == '1') {
+ setAdbEnabled(true);
+ } else if (enable == '0') {
+ setAdbEnabled(false);
+ }
+ SystemProperties.set("persist.service.adb.enable", "");
+ }
+
+ // register observer to listen for settings changes
+ mContentResolver.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
+ false, new AdbSettingsObserver());
+
+ // Watch for USB configuration changes
+ mUEventObserver.startObserving(USB_STATE_MATCH);
+ mUEventObserver.startObserving(ACCESSORY_START_MATCH);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error initializing UsbHandler", e);
+ }
+ }
+
+ public void sendMessage(int what, boolean arg) {
+ removeMessages(what);
+ Message m = Message.obtain(this, what);
+ m.arg1 = (arg ? 1 : 0);
+ sendMessage(m);
+ }
+
+ public void sendMessage(int what, Object arg) {
+ removeMessages(what);
+ Message m = Message.obtain(this, what);
+ m.obj = arg;
+ sendMessage(m);
+ }
+
+ public void sendMessage(int what, Object arg0, boolean arg1) {
+ removeMessages(what);
+ Message m = Message.obtain(this, what);
+ m.obj = arg0;
+ m.arg1 = (arg1 ? 1 : 0);
+ sendMessage(m);
+ }
+
+ public void updateState(String state) {
+ int connected, configured;
+
+ if ("DISCONNECTED".equals(state)) {
+ connected = 0;
+ configured = 0;
+ } else if ("CONNECTED".equals(state)) {
+ connected = 1;
+ configured = 0;
+ } else if ("CONFIGURED".equals(state)) {
+ connected = 1;
+ configured = 1;
+ } else {
+ Slog.e(TAG, "unknown state " + state);
+ return;
+ }
+ removeMessages(MSG_UPDATE_STATE);
+ Message msg = Message.obtain(this, MSG_UPDATE_STATE);
+ msg.arg1 = connected;
+ msg.arg2 = configured;
+ // debounce disconnects to avoid problems bringing up USB tethering
+ sendMessageDelayed(msg, (connected == 0) ? UPDATE_DELAY : 0);
+ }
+
+ private boolean waitForState(String state) {
+ // wait for the transition to complete.
+ // give up after 1 second.
+ for (int i = 0; i < 20; i++) {
+ // State transition is done when sys.usb.conf.done is set to the new configuration
+ if (state.equals(SystemProperties.get("sys.usb.state"))) return true;
+ try {
+ // try again in 50ms
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ }
+ Log.e(TAG, "waitForState(" + state + ") FAILED");
+ return false;
+ }
+
+ private boolean setUsbConfig(String config) {
+ Log.d(TAG, "setUsbConfig(" + config + ")");
+ // set the new configuration
+ SystemProperties.set("sys.usb.config", config);
+ return waitForState(config);
+ }
+
+ private void doSetCurrentFunctions(String functions) {
+ if (!mCurrentFunctions.equals(functions)) {
+ if (!setUsbConfig("none") || !setUsbConfig(functions)) {
+ Log.e(TAG, "Failed to switch USB configuration to " + functions);
+ // revert to previous configuration if we fail
+ setUsbConfig(mCurrentFunctions);
+ } else {
+ mCurrentFunctions = functions;
}
}
}
- };
+
+ private void setAdbEnabled(boolean enable) {
+ if (enable != mAdbEnabled) {
+ mAdbEnabled = enable;
+ String functions;
+ // Due to the persist.sys.usb.config property trigger, changing adb state requires
+ // switching to default function
+ if (enable) {
+ functions = addFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ functions = removeFunction(mDefaultFunctions, UsbManager.USB_FUNCTION_ADB);
+ }
+ setCurrentFunction(functions, true);
+ updateAdbNotification(mAdbEnabled && mConnected);
+ }
+ }
+
+ private void setEnabledFunctions(String functionList) {
+ if (mAdbEnabled) {
+ functionList = addFunction(functionList, UsbManager.USB_FUNCTION_ADB);
+ } else {
+ functionList = removeFunction(functionList, UsbManager.USB_FUNCTION_ADB);
+ }
+ doSetCurrentFunctions(functionList);
+ }
+
+ private void updateCurrentAccessory() {
+ if (!mHasUsbAccessory) return;
+
+ if (mConfigured) {
+ String[] strings = nativeGetAccessoryStrings();
+ if (strings != null) {
+ mCurrentAccessory = new UsbAccessory(strings);
+ Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
+ // defer accessoryAttached if system is not ready
+ if (mSystemReady) {
+ mSettingsManager.accessoryAttached(mCurrentAccessory);
+ } else {
+ mDeferAccessoryAttached = true;
+ }
+ } else {
+ Log.e(TAG, "nativeGetAccessoryStrings failed");
+ }
+ } else if (!mConnected) {
+ // make sure accessory mode is off
+ // and restore default functions
+ Log.d(TAG, "exited USB accessory mode");
+ setEnabledFunctions(mDefaultFunctions);
+
+ if (mCurrentAccessory != null) {
+ if (mSystemReady) {
+ mSettingsManager.accessoryDetached(mCurrentAccessory);
+ }
+ mCurrentAccessory = null;
+ }
+ }
+ }
+
+ private void updateUsbState() {
+ // send a sticky broadcast containing current USB state
+ Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
+ intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
+
+ if (mCurrentFunctions != null) {
+ String[] functions = mCurrentFunctions.split(",");
+ for (int i = 0; i < functions.length; i++) {
+ intent.putExtra(functions[i], true);
+ }
+ }
+
+ mContext.sendStickyBroadcast(intent);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_STATE:
+ mConnected = (msg.arg1 == 1);
+ mConfigured = (msg.arg2 == 1);
+ updateUsbNotification(mConnected);
+ updateAdbNotification(mAdbEnabled && mConnected);
+ if (containsFunction(mCurrentFunctions,
+ UsbManager.USB_FUNCTION_ACCESSORY)) {
+ updateCurrentAccessory();
+ }
+
+ if (!mConnected) {
+ // restore defaults when USB is disconnected
+ doSetCurrentFunctions(mDefaultFunctions);
+ }
+ if (mSystemReady) {
+ updateUsbState();
+ }
+ break;
+ case MSG_ENABLE_ADB:
+ setAdbEnabled(msg.arg1 == 1);
+ break;
+ case MSG_SET_CURRENT_FUNCTION:
+ String function = (String)msg.obj;
+ boolean makeDefault = (msg.arg1 == 1);
+ if (makeDefault) {
+ if (function == null) {
+ throw new NullPointerException();
+ }
+ if (mAdbEnabled) {
+ function = addFunction(function, UsbManager.USB_FUNCTION_ADB);
+ }
+
+ setUsbConfig("none");
+ // setting this property will change the current USB state
+ // via a property trigger
+ SystemProperties.set("persist.sys.usb.config", function);
+ if (waitForState(function)) {
+ mCurrentFunctions = function;
+ mDefaultFunctions = function;
+ }
+ } else {
+ if (function == null) {
+ function = mDefaultFunctions;
+ }
+ setEnabledFunctions(function);
+ }
+ break;
+ case MSG_SYSTEM_READY:
+ updateUsbNotification(mConnected);
+ updateAdbNotification(mAdbEnabled && mConnected);
+ updateUsbState();
+ if (mCurrentAccessory != null && mDeferAccessoryAttached) {
+ mSettingsManager.accessoryAttached(mCurrentAccessory);
+ }
+ break;
+ }
+ }
+
+ public UsbAccessory getCurrentAccessory() {
+ return mCurrentAccessory;
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw) {
+ pw.println(" USB Device State:");
+ pw.println(" Current Functions: " + mCurrentFunctions);
+ pw.println(" Default Functions: " + mDefaultFunctions);
+ pw.println(" mConnected: " + mConnected);
+ pw.println(" mConfigured: " + mConfigured);
+ pw.println(" mCurrentAccessory: " + mCurrentAccessory);
+ }
+ }
+
+ /* returns the currently attached USB accessory */
+ public UsbAccessory getCurrentAccessory() {
+ return mHandler.getCurrentAccessory();
+ }
+
+ /* opens the currently attached USB accessory */
+ public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
+ UsbAccessory currentAccessory = mHandler.getCurrentAccessory();
+ if (currentAccessory == null) {
+ throw new IllegalArgumentException("no accessory attached");
+ }
+ if (!currentAccessory.equals(accessory)) {
+ String error = accessory.toString()
+ + " does not match current accessory "
+ + currentAccessory;
+ throw new IllegalArgumentException(error);
+ }
+ mSettingsManager.checkPermission(accessory);
+ return nativeOpenAccessory();
+ }
+
+ public void setCurrentFunction(String function, boolean makeDefault) {
+ mHandler.sendMessage(MSG_SET_CURRENT_FUNCTION, function, makeDefault);
+ }
+
+ public void setMassStorageBackingFile(String path) {
+ if (path == null) path = "";
+ try {
+ FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path);
+ } catch (IOException e) {
+ Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH);
+ }
+ }
public void dump(FileDescriptor fd, PrintWriter pw) {
- synchronized (mLock) {
- pw.println(" USB Device State:");
- pw.print(" Enabled Functions: ");
- for (int i = 0; i < mEnabledFunctions.size(); i++) {
- pw.print(mEnabledFunctions.get(i) + " ");
- }
- pw.println("");
- pw.print(" Default Functions: ");
- for (int i = 0; i < mDefaultFunctions.size(); i++) {
- pw.print(mDefaultFunctions.get(i) + " ");
- }
- pw.println("");
- pw.println(" mConnected: " + mConnected + ", mConfiguration: " + mConfiguration);
- pw.println(" mCurrentAccessory: " + mCurrentAccessory);
+ if (mHandler != null) {
+ mHandler.dump(fd, pw);
}
}
diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java
index 21e5997c..9f2c17a 100644
--- a/services/java/com/android/server/usb/UsbService.java
+++ b/services/java/com/android/server/usb/UsbService.java
@@ -50,7 +50,7 @@
if (pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mHostManager = new UsbHostManager(context, mSettingsManager);
}
- if (new File("/sys/class/usb_composite").exists()) {
+ if (new File("/sys/class/android_usb").exists()) {
mDeviceManager = new UsbDeviceManager(context, mSettingsManager);
}
}
@@ -92,7 +92,7 @@
/* opens the currently attached USB accessory (device mode) */
public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
if (mDeviceManager != null) {
- return openAccessory(accessory);
+ return mDeviceManager.openAccessory(accessory);
} else {
return null;
}
@@ -146,6 +146,24 @@
mSettingsManager.clearDefaults(packageName);
}
+ public void setCurrentFunction(String function, boolean makeDefault) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ if (mDeviceManager != null) {
+ mDeviceManager.setCurrentFunction(function, makeDefault);
+ } else {
+ throw new IllegalStateException("USB device mode not supported");
+ }
+ }
+
+ public void setMassStorageBackingFile(String path) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+ if (mDeviceManager != null) {
+ mDeviceManager.setMassStorageBackingFile(path);
+ } else {
+ throw new IllegalStateException("USB device mode not supported");
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 3be8af6..6806634 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -152,6 +153,8 @@
}
mUpdateInputWindowsNeeded = false;
+ if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED updateInputWindowsLw");
+
// Populate the input window list with information about all of the windows that
// could potentially receive input.
// As an optimization, we could try to prune the list of windows but this turns
@@ -232,6 +235,8 @@
// Clear the list in preparation for the next round.
// Also avoids keeping InputChannel objects referenced unnecessarily.
mTempInputWindows.clear();
+
+ if (false) Slog.d(WindowManagerService.TAG, "<<<<<<< EXITED updateInputWindowsLw");
}
/* Notifies that the input device configuration has changed. */
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 0f09356..50b251f 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -153,11 +153,13 @@
int requestedWidth, int requestedHeight, int viewFlags,
boolean insetsPending, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
- //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
+ if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from "
+ + Binder.getCallingPid());
int res = mService.relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, insetsPending,
outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
- //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+ if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to "
+ + Binder.getCallingPid());
return res;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 1c87f5b..3bf309b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2776,6 +2776,13 @@
Binder.restoreCallingIdentity(origId);
}
+ public float getWindowCompatibilityScale(IBinder windowToken) {
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(windowToken);
+ return (windowState != null) ? windowState.mGlobalScale : 1.0f;
+ }
+ }
+
private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
+ (lp != null ? lp.packageName : null)
@@ -5557,10 +5564,10 @@
private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
int dw, int dh) {
- dm.unscaledWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
- dm.unscaledHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
+ dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
+ dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
- int size = (int)(((dm.unscaledWidthPixels / scale) / dm.density) + .5f);
+ int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
if (curSize == 0 || size < curSize) {
curSize = size;
}
@@ -5635,9 +5642,9 @@
// Override display width and height with what we are computing,
// to be sure they remain consistent.
- dm.widthPixels = dm.unscaledWidthPixels = mAppDisplayWidth
+ dm.widthPixels = dm.noncompatWidthPixels = mAppDisplayWidth
= mPolicy.getNonDecorDisplayWidth(mRotation, dw);
- dm.heightPixels = dm.unscaledHeightPixels = mAppDisplayHeight
+ dm.heightPixels = dm.noncompatHeightPixels = mAppDisplayHeight
= mPolicy.getNonDecorDisplayHeight(mRotation, dh);
mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
@@ -7817,18 +7824,30 @@
TAG, "Placing surface #" + i + " " + w.mSurface
+ ": new=" + w.mShownFrame);
- int width, height;
- if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
- // for a scaled surface, we just want to use
- // the requested size.
- width = w.mRequestedWidth;
- height = w.mRequestedHeight;
- } else {
- width = w.mCompatFrame.width();
- height = w.mCompatFrame.height();
- }
-
if (w.mSurface != null) {
+ int width, height;
+ if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
+ // for a scaled surface, we just want to use
+ // the requested size.
+ width = w.mRequestedWidth;
+ height = w.mRequestedHeight;
+ } else {
+ width = w.mCompatFrame.width();
+ height = w.mCompatFrame.height();
+ }
+
+ if (width < 1) {
+ width = 1;
+ }
+ if (height < 1) {
+ height = 1;
+ }
+ final boolean surfaceResized = w.mSurfaceW != width || w.mSurfaceH != height;
+ if (surfaceResized) {
+ w.mSurfaceW = width;
+ w.mSurfaceH = height;
+ }
+
if (w.mSurfaceX != w.mShownFrame.left
|| w.mSurfaceY != w.mShownFrame.top) {
try {
@@ -7848,21 +7867,11 @@
}
}
- if (width < 1) {
- width = 1;
- }
- if (height < 1) {
- height = 1;
- }
-
- if (w.mSurfaceW != width || w.mSurfaceH != height) {
+ if (surfaceResized) {
try {
if (SHOW_TRANSACTIONS) logSurface(w,
- "SIZE " + w.mShownFrame.width() + "x"
- + w.mShownFrame.height(), null);
+ "SIZE " + width + "x" + height, null);
w.mSurfaceResized = true;
- w.mSurfaceW = width;
- w.mSurfaceH = height;
w.mSurface.setSize(width, height);
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
@@ -7878,9 +7887,9 @@
}
if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
- w.mContentInsetsChanged =
+ w.mContentInsetsChanged |=
!w.mLastContentInsets.equals(w.mContentInsets);
- w.mVisibleInsetsChanged =
+ w.mVisibleInsetsChanged |=
!w.mLastVisibleInsets.equals(w.mVisibleInsets);
boolean configChanged =
w.mConfiguration != mCurConfiguration
@@ -7892,24 +7901,20 @@
}
if (localLOGV) Slog.v(TAG, "Resizing " + w
+ ": configChanged=" + configChanged
- + " last=" + w.mLastCompatFrame + " frame=" + w.mCompatFrame);
- boolean frameChanged = !w.mLastCompatFrame.equals(w.mCompatFrame);
- if (frameChanged
- || w.mContentInsetsChanged
+ + " last=" + w.mLastFrame + " frame=" + w.mFrame);
+ w.mLastFrame.set(w.mFrame);
+ if (w.mContentInsetsChanged
|| w.mVisibleInsetsChanged
|| w.mSurfaceResized
|| configChanged) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG, "Resize reasons: "
- + "frameChanged=" + frameChanged
+ " contentInsetsChanged=" + w.mContentInsetsChanged
+ " visibleInsetsChanged=" + w.mVisibleInsetsChanged
+ " surfaceResized=" + w.mSurfaceResized
+ " configChanged=" + configChanged);
}
- w.mLastFrame.set(w.mFrame);
- w.mLastCompatFrame.set(w.mCompatFrame);
w.mLastContentInsets.set(w.mContentInsets);
w.mLastVisibleInsets.set(w.mVisibleInsets);
// If the screen is currently frozen, then keep
@@ -7944,9 +7949,12 @@
w.mAppToken.allDrawn = false;
}
}
- if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
- "Resizing window " + w + " to " + w.mCompatFrame);
- mResizingWindows.add(w);
+ if (!mResizingWindows.contains(w)) {
+ if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
+ "Resizing window " + w + " to " + w.mSurfaceW
+ + "x" + w.mSurfaceH);
+ mResizingWindows.add(w);
+ }
} else if (w.mOrientationChanging) {
if (!w.mDrawPending && !w.mCommitDrawPending) {
if (DEBUG_ORIENTATION) Slog.v(TAG,
@@ -8241,13 +8249,12 @@
if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
&& configChanged) {
Slog.i(TAG, "Sending new config to window " + win + ": "
- + win.mCompatFrame.width() + "x" + win.mCompatFrame.height()
+ + win.mSurfaceW + "x" + win.mSurfaceH
+ " / " + mCurConfiguration + " / 0x"
+ Integer.toHexString(diff));
}
win.mConfiguration = mCurConfiguration;
- win.mClient.resized(win.mCompatFrame.width(),
- win.mCompatFrame.height(), win.mLastContentInsets,
+ win.mClient.resized(win.mSurfaceW, win.mSurfaceH, win.mLastContentInsets,
win.mLastVisibleInsets, win.mDrawPending,
configChanged ? win.mConfiguration : null);
win.mContentInsetsChanged = false;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 587685e..b370ec9 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -111,7 +111,6 @@
* applied).
*/
final Rect mShownFrame = new Rect();
- final Rect mLastShownFrame = new Rect();
/**
* Set when we have changed the size of the surface, to know that
@@ -182,7 +181,6 @@
// Frame that is scaled to the application's coordinate space when in
// screen size compatibility mode.
final Rect mCompatFrame = new Rect();
- final Rect mLastCompatFrame = new Rect();
final Rect mContainingFrame = new Rect();
final Rect mDisplayFrame = new Rect();
@@ -1584,15 +1582,12 @@
}
pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
pw.print(prefix); pw.print("mShownFrame=");
- mShownFrame.printShortString(pw);
- pw.print(" last="); mLastShownFrame.printShortString(pw);
- pw.println();
+ mShownFrame.printShortString(pw); pw.println();
pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
pw.print(" last="); mLastFrame.printShortString(pw);
pw.println();
if (mEnforceSizeCompat) {
pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
- pw.print(" last="); mLastCompatFrame.printShortString(pw);
pw.println();
}
pw.print(prefix); pw.print("mContainingFrame=");
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index ae7fbfe..a0ea92b 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -42,6 +42,9 @@
namespace android
{
+static int inet4 = -1;
+static int inet6 = -1;
+
static inline in_addr_t *as_in_addr(sockaddr *sa) {
return &((sockaddr_in *)sa)->sin_addr.s_addr;
}
@@ -51,11 +54,9 @@
#define SYSTEM_ERROR -1
#define BAD_ARGUMENT -2
-static int create_interface(int mtu, char *name, int *index)
+static int create_interface(int mtu)
{
- int tun = open("/dev/tun", O_RDWR);
- int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
- int flags;
+ int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);
ifreq ifr4;
memset(&ifr4, 0, sizeof(ifr4));
@@ -81,38 +82,45 @@
goto error;
}
- // Get interface index.
- if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
- LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno));
- goto error;
- }
-
- // Make it non-blocking.
- flags = fcntl(tun, F_GETFL, 0);
- if (flags == -1 || fcntl(tun, F_SETFL, flags | O_NONBLOCK)) {
- LOGE("Cannot set non-blocking on %s: %s", ifr4.ifr_name, strerror(errno));
- goto error;
- }
-
- strcpy(name, ifr4.ifr_name);
- *index = ifr4.ifr_ifindex;
- close(inet4);
return tun;
error:
close(tun);
- close(inet4);
return SYSTEM_ERROR;
}
-static int set_addresses(const char *name, int index, const char *addresses)
+static int get_interface_name(char *name, int tun)
{
- int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
- int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ ifreq ifr4;
+ if (ioctl(tun, TUNGETIFF, &ifr4)) {
+ LOGE("Cannot get interface name: %s", strerror(errno));
+ return SYSTEM_ERROR;
+ }
+ strncpy(name, ifr4.ifr_name, IFNAMSIZ);
+ return 0;
+}
+
+static int get_interface_index(const char *name)
+{
+ ifreq ifr4;
+ strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+ if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
+ LOGE("Cannot get index of %s: %s", name, strerror(errno));
+ return SYSTEM_ERROR;
+ }
+ return ifr4.ifr_ifindex;
+}
+
+static int set_addresses(const char *name, const char *addresses)
+{
+ int index = get_interface_index(name);
+ if (index < 0) {
+ return index;
+ }
ifreq ifr4;
memset(&ifr4, 0, sizeof(ifr4));
- strcpy(ifr4.ifr_name, name);
+ strncpy(ifr4.ifr_name, name, IFNAMSIZ);
ifr4.ifr_addr.sa_family = AF_INET;
in6_ifreq ifr6;
@@ -121,7 +129,6 @@
char address[65];
int prefix;
-
int chars;
int count = 0;
@@ -164,7 +171,7 @@
break;
}
}
- LOGV("Address added on %s: %s/%d", name, address, prefix);
+ LOGD("Address added on %s: %s/%d", name, address, prefix);
++count;
}
@@ -177,15 +184,15 @@
count = BAD_ARGUMENT;
}
- close(inet4);
- close(inet6);
return count;
}
-static int set_routes(const char *name, int index, const char *routes)
+static int set_routes(const char *name, const char *routes)
{
- int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
- int inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ int index = get_interface_index(name);
+ if (index < 0) {
+ return index;
+ }
rtentry rt4;
memset(&rt4, 0, sizeof(rt4));
@@ -201,7 +208,6 @@
char address[65];
int prefix;
-
int chars;
int count = 0;
@@ -211,32 +217,50 @@
if (strchr(address, ':')) {
// Add an IPv6 route.
if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
- prefix < 1 || prefix > 128) {
+ prefix < 0 || prefix > 128) {
count = BAD_ARGUMENT;
break;
}
- rt6.rtmsg_dst_len = prefix;
+ rt6.rtmsg_dst_len = prefix ? prefix : 1;
if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
break;
}
+
+ if (!prefix) {
+ // Split the route instead of replacing the default route.
+ rt6.rtmsg_dst.s6_addr[0] ^= 0x80;
+ if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
+ count = SYSTEM_ERROR;
+ break;
+ }
+ }
} else {
// Add an IPv4 route.
if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
- prefix < 1 || prefix > 32) {
+ prefix < 0 || prefix > 32) {
count = BAD_ARGUMENT;
break;
}
- in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
+ in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 1;
*as_in_addr(&rt4.rt_genmask) = htonl(mask);
if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
break;
}
+
+ if (!prefix) {
+ // Split the route instead of replacing the default route.
+ *as_in_addr(&rt4.rt_dst) ^= htonl(0x80000000);
+ if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
+ count = SYSTEM_ERROR;
+ break;
+ }
+ }
}
- LOGV("Route added on %s: %s/%d", name, address, prefix);
+ LOGD("Route added on %s: %s/%d", name, address, prefix);
++count;
}
@@ -250,43 +274,24 @@
count = BAD_ARGUMENT;
}
- close(inet4);
- close(inet6);
return count;
}
-static int get_interface_name(char *name, int tun)
-{
- ifreq ifr4;
- if (ioctl(tun, TUNGETIFF, &ifr4)) {
- LOGE("Cannot get interface name: %s", strerror(errno));
- return SYSTEM_ERROR;
- }
- strcpy(name, ifr4.ifr_name);
- return 0;
-}
-
static int reset_interface(const char *name)
{
- int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
ifreq ifr4;
- ifr4.ifr_flags = 0;
strncpy(ifr4.ifr_name, name, IFNAMSIZ);
+ ifr4.ifr_flags = 0;
if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) {
LOGE("Cannot reset %s: %s", name, strerror(errno));
- close(inet4);
return SYSTEM_ERROR;
}
- close(inet4);
return 0;
}
static int check_interface(const char *name)
{
- int inet4 = socket(AF_INET, SOCK_DGRAM, 0);
-
ifreq ifr4;
strncpy(ifr4.ifr_name, name, IFNAMSIZ);
ifr4.ifr_flags = 0;
@@ -294,7 +299,6 @@
if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) {
LOGE("Cannot check %s: %s", name, strerror(errno));
}
- close(inet4);
return ifr4.ifr_flags;
}
@@ -318,86 +322,108 @@
}
}
-static jint establish(JNIEnv *env, jobject thiz,
- jint mtu, jstring jAddresses, jstring jRoutes)
+static jint createInterface(JNIEnv *env, jobject thiz, jint mtu)
{
- char name[IFNAMSIZ];
- int index;
- int tun = create_interface(mtu, name, &index);
+ int tun = create_interface(mtu);
if (tun < 0) {
throwException(env, tun, "Cannot create interface");
return -1;
}
- LOGD("%s is created", name);
-
- const char *addresses;
- const char *routes;
- int count;
-
- // Addresses are required.
- addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
- if (!addresses) {
- jniThrowNullPointerException(env, "address");
- goto error;
- }
- count = set_addresses(name, index, addresses);
- env->ReleaseStringUTFChars(jAddresses, addresses);
- if (count <= 0) {
- throwException(env, count, "Cannot set address");
- goto error;
- }
- LOGD("Configured %d address(es) on %s", count, name);
-
- // Routes are optional.
- routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
- if (routes) {
- count = set_routes(name, index, routes);
- env->ReleaseStringUTFChars(jRoutes, routes);
- if (count < 0) {
- throwException(env, count, "Cannot set route");
- goto error;
- }
- LOGD("Configured %d route(s) on %s", count, name);
- }
-
return tun;
-
-error:
- close(tun);
- LOGD("%s is destroyed", name);
- return -1;
}
-static jstring getName(JNIEnv *env, jobject thiz, jint fd)
+static jstring getInterfaceName(JNIEnv *env, jobject thiz, jint tun)
{
char name[IFNAMSIZ];
- if (get_interface_name(name, fd) < 0) {
+ if (get_interface_name(name, tun) < 0) {
throwException(env, SYSTEM_ERROR, "Cannot get interface name");
return NULL;
}
return env->NewStringUTF(name);
}
-static void reset(JNIEnv *env, jobject thiz, jstring jName)
+static jint setAddresses(JNIEnv *env, jobject thiz, jstring jName,
+ jstring jAddresses)
{
- const char *name = jName ?
- env->GetStringUTFChars(jName, NULL) : NULL;
+ const char *name = NULL;
+ const char *addresses = NULL;
+ int count = -1;
+
+ name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+ if (!name) {
+ jniThrowNullPointerException(env, "name");
+ goto error;
+ }
+ addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
+ if (!addresses) {
+ jniThrowNullPointerException(env, "addresses");
+ goto error;
+ }
+ count = set_addresses(name, addresses);
+ if (count < 0) {
+ throwException(env, count, "Cannot set address");
+ count = -1;
+ }
+
+error:
+ if (name) {
+ env->ReleaseStringUTFChars(jName, name);
+ }
+ if (addresses) {
+ env->ReleaseStringUTFChars(jAddresses, addresses);
+ }
+ return count;
+}
+
+static jint setRoutes(JNIEnv *env, jobject thiz, jstring jName,
+ jstring jRoutes)
+{
+ const char *name = NULL;
+ const char *routes = NULL;
+ int count = -1;
+
+ name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
+ if (!name) {
+ jniThrowNullPointerException(env, "name");
+ goto error;
+ }
+ routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
+ if (!routes) {
+ jniThrowNullPointerException(env, "routes");
+ goto error;
+ }
+ count = set_routes(name, routes);
+ if (count < 0) {
+ throwException(env, count, "Cannot set address");
+ count = -1;
+ }
+
+error:
+ if (name) {
+ env->ReleaseStringUTFChars(jName, name);
+ }
+ if (routes) {
+ env->ReleaseStringUTFChars(jRoutes, routes);
+ }
+ return count;
+}
+
+static void resetInterface(JNIEnv *env, jobject thiz, jstring jName)
+{
+ const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
if (!name) {
jniThrowNullPointerException(env, "name");
return;
}
if (reset_interface(name) < 0) {
throwException(env, SYSTEM_ERROR, "Cannot reset interface");
- } else {
- LOGD("%s is deactivated", name);
}
env->ReleaseStringUTFChars(jName, name);
}
-static jint check(JNIEnv *env, jobject thiz, jstring jName)
+static jint checkInterface(JNIEnv *env, jobject thiz, jstring jName)
{
- const char *name = jName ?
- env->GetStringUTFChars(jName, NULL) : NULL;
+ const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
if (!name) {
jniThrowNullPointerException(env, "name");
return 0;
@@ -407,10 +433,9 @@
return flags;
}
-static void protect(JNIEnv *env, jobject thiz, jint fd, jstring jName)
+static void protectSocket(JNIEnv *env, jobject thiz, jint fd, jstring jName)
{
- const char *name = jName ?
- env->GetStringUTFChars(jName, NULL) : NULL;
+ const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
if (!name) {
jniThrowNullPointerException(env, "name");
return;
@@ -424,15 +449,23 @@
//------------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"nativeEstablish", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)establish},
- {"nativeGetName", "(I)Ljava/lang/String;", (void *)getName},
- {"nativeReset", "(Ljava/lang/String;)V", (void *)reset},
- {"nativeCheck", "(Ljava/lang/String;)I", (void *)check},
- {"nativeProtect", "(ILjava/lang/String;)V", (void *)protect},
+ {"jniCreateInterface", "(I)I", (void *)createInterface},
+ {"jniGetInterfaceName", "(I)Ljava/lang/String;", (void *)getInterfaceName},
+ {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
+ {"jniSetRoutes", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setRoutes},
+ {"jniResetInterface", "(Ljava/lang/String;)V", (void *)resetInterface},
+ {"jniCheckInterface", "(Ljava/lang/String;)I", (void *)checkInterface},
+ {"jniProtectSocket", "(ILjava/lang/String;)V", (void *)protectSocket},
};
int register_android_server_connectivity_Vpn(JNIEnv *env)
{
+ if (inet4 == -1) {
+ inet4 = socket(AF_INET, SOCK_DGRAM, 0);
+ }
+ if (inet6 == -1) {
+ inet6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ }
return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn",
gMethods, NELEM(gMethods));
}
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index 6d4ad9a..87ffcba 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -42,6 +42,7 @@
static jmethodID method_reportNiNotification;
static jmethodID method_requestRefLocation;
static jmethodID method_requestSetID;
+static jmethodID method_requestUtcTime;
static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
@@ -122,6 +123,13 @@
release_wake_lock(WAKE_LOCK_NAME);
}
+static void request_utc_time_callback()
+{
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
{
return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
@@ -137,6 +145,7 @@
acquire_wakelock_callback,
release_wakelock_callback,
create_thread_callback,
+ request_utc_time_callback,
};
static void xtra_download_request_callback()
@@ -232,6 +241,7 @@
"(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
+ method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 0ae7929..64d214b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -31,6 +31,7 @@
#include <binder/BinderService.h>
#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
#include <gui/ISensorServer.h>
#include <gui/ISensorEventConnection.h>
@@ -58,8 +59,7 @@
*/
SensorService::SensorService()
- : mDump("android.permission.DUMP"),
- mInitCheck(NO_INIT)
+ : mInitCheck(NO_INIT)
{
}
@@ -166,12 +166,14 @@
delete mSensorMap.valueAt(i);
}
+static const String16 sDump("android.permission.DUMP");
+
status_t SensorService::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 1024;
char buffer[SIZE];
String8 result;
- if (!mDump.checkCalling()) {
+ if (!PermissionCache::checkCallingPermission(sDump)) {
snprintf(buffer, SIZE, "Permission Denial: "
"can't dump SurfaceFlinger from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 4d0f1d9..85f4ecb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -27,7 +27,6 @@
#include <utils/RefBase.h>
#include <binder/BinderService.h>
-#include <binder/Permission.h>
#include <gui/Sensor.h>
#include <gui/SensorChannel.h>
@@ -117,7 +116,6 @@
Vector<Sensor> mUserSensorList;
DefaultKeyedVector<int, SensorInterface*> mSensorMap;
Vector<SensorInterface *> mVirtualSensorList;
- Permission mDump;
status_t mInitCheck;
// protected by mLock
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2bab6a8..35e29a6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -101,9 +101,8 @@
}
void Layer::onFrameQueued() {
- if (android_atomic_or(1, &mQueuedFrames) == 0) {
- mFlinger->signalEvent();
- }
+ android_atomic_inc(&mQueuedFrames);
+ mFlinger->signalEvent();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -406,20 +405,18 @@
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
- if (android_atomic_and(0, &mQueuedFrames)) {
+ if (mQueuedFrames > 0) {
+ // signal another event if we have more frames pending
+ if (android_atomic_dec(&mQueuedFrames) > 1) {
+ mFlinger->signalEvent();
+ }
+
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
// something happened!
recomputeVisibleRegions = true;
return;
}
- // signal another event if we have more frames waiting
- if (mSurfaceTexture->getQueuedCount()) {
- if (android_atomic_or(1, &mQueuedFrames) == 0) {
- mFlinger->signalEvent();
- }
- }
-
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
mSurfaceTexture->getTransformMatrix(mTextureMatrix);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 97edfee..685613e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -32,6 +32,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h>
+#include <binder/PermissionCache.h>
#include <utils/String8.h>
#include <utils/String16.h>
@@ -67,17 +68,19 @@
namespace android {
// ---------------------------------------------------------------------------
+const String16 sHardwareTest("android.permission.HARDWARE_TEST");
+const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
+const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
+const String16 sDump("android.permission.DUMP");
+
+// ---------------------------------------------------------------------------
+
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(), Thread(false),
mTransactionFlags(0),
- mTransactionCount(0),
mResizeTransationPending(false),
mLayersRemoved(false),
mBootTime(systemTime()),
- mHardwareTest("android.permission.HARDWARE_TEST"),
- mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
- mReadFramebuffer("android.permission.READ_FRAME_BUFFER"),
- mDump("android.permission.DUMP"),
mVisibleRegionsDirty(false),
mHwWorkListDirty(false),
mDeferReleaseConsole(false),
@@ -381,13 +384,11 @@
handleConsoleEvents();
}
- if (LIKELY(mTransactionCount == 0)) {
- // if we're in a global transaction, don't do anything.
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
- if (LIKELY(transactionFlags)) {
- handleTransaction(transactionFlags);
- }
+ // if we're in a global transaction, don't do anything.
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ uint32_t transactionFlags = peekTransactionFlags(mask);
+ if (UNLIKELY(transactionFlags)) {
+ handleTransaction(transactionFlags);
}
// post surfaces (if needed)
@@ -1172,28 +1173,33 @@
return old;
}
-void SurfaceFlinger::openGlobalTransaction()
-{
- android_atomic_inc(&mTransactionCount);
-}
-void SurfaceFlinger::closeGlobalTransaction()
-{
- if (android_atomic_dec(&mTransactionCount) == 1) {
- signalEvent();
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
+ Mutex::Autolock _l(mStateLock);
- // if there is a transaction with a resize, wait for it to
- // take effect before returning.
- Mutex::Autolock _l(mStateLock);
- while (mResizeTransationPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
- mResizeTransationPending = false;
- break;
- }
+ uint32_t flags = 0;
+ const size_t count = state.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const ComposerState& s(state[i]);
+ sp<Client> client( static_cast<Client *>(s.client.get()) );
+ flags |= setClientStateLocked(client, s.state);
+ }
+ if (flags) {
+ setTransactionFlags(flags);
+ }
+
+ signalEvent();
+
+ // if there is a transaction with a resize, wait for it to
+ // take effect before returning.
+ while (mResizeTransationPending) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
+ mResizeTransationPending = false;
+ break;
}
}
}
@@ -1389,60 +1395,52 @@
return err;
}
-status_t SurfaceFlinger::setClientState(
+uint32_t SurfaceFlinger::setClientStateLocked(
const sp<Client>& client,
- int32_t count,
- const layer_state_t* states)
+ const layer_state_t& s)
{
- Mutex::Autolock _l(mStateLock);
uint32_t flags = 0;
- for (int i=0 ; i<count ; i++) {
- const layer_state_t& s(states[i]);
- sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- if (what & ePositionChanged) {
- if (layer->setPosition(s.x, s.y))
- flags |= eTraversalNeeded;
- }
- if (what & eLayerChanged) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- if (what & eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- mResizeTransationPending = true;
- }
- }
- if (what & eAlphaChanged) {
- if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
- flags |= eTraversalNeeded;
- }
- if (what & eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
- flags |= eTraversalNeeded;
- }
- if (what & eTransparentRegionChanged) {
- if (layer->setTransparentRegionHint(s.transparentRegion))
- flags |= eTraversalNeeded;
- }
- if (what & eVisibilityChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
+ sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
+ if (layer != 0) {
+ const uint32_t what = s.what;
+ if (what & ePositionChanged) {
+ if (layer->setPosition(s.x, s.y))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eLayerChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setLayer(s.z)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
}
}
+ if (what & eSizeChanged) {
+ if (layer->setSize(s.w, s.h)) {
+ flags |= eTraversalNeeded;
+ mResizeTransationPending = true;
+ }
+ }
+ if (what & eAlphaChanged) {
+ if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eMatrixChanged) {
+ if (layer->setMatrix(s.matrix))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eTransparentRegionChanged) {
+ if (layer->setTransparentRegionHint(s.transparentRegion))
+ flags |= eTraversalNeeded;
+ }
+ if (what & eVisibilityChanged) {
+ if (layer->setFlags(s.flags, s.mask))
+ flags |= eTraversalNeeded;
+ }
}
- if (flags) {
- setTransactionFlags(flags);
- }
- return NO_ERROR;
+ return flags;
}
void SurfaceFlinger::screenReleased(int dpy)
@@ -1464,7 +1462,8 @@
const size_t SIZE = 4096;
char buffer[SIZE];
String8 result;
- if (!mDump.checkCalling()) {
+
+ if (!PermissionCache::checkCallingPermission(sDump)) {
snprintf(buffer, SIZE, "Permission Denial: "
"can't dump SurfaceFlinger from pid=%d, uid=%d\n",
IPCThreadState::self()->getCallingPid(),
@@ -1583,8 +1582,7 @@
{
switch (code) {
case CREATE_CONNECTION:
- case OPEN_GLOBAL_TRANSACTION:
- case CLOSE_GLOBAL_TRANSACTION:
+ case SET_TRANSACTION_STATE:
case SET_ORIENTATION:
case FREEZE_DISPLAY:
case UNFREEZE_DISPLAY:
@@ -1596,7 +1594,8 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
+ if ((uid != AID_GRAPHICS) &&
+ !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
LOGE("Permission Denial: "
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
@@ -1609,7 +1608,8 @@
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) && !mReadFramebuffer.check(pid, uid)) {
+ if ((uid != AID_GRAPHICS) &&
+ !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
LOGE("Permission Denial: "
"can't read framebuffer pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
@@ -1621,7 +1621,7 @@
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- if (UNLIKELY(!mHardwareTest.checkCalling())) {
+ if (UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
IPCThreadState* ipc = IPCThreadState::self();
const int pid = ipc->getCallingPid();
const int uid = ipc->getCallingUid();
@@ -1799,10 +1799,10 @@
const GLfloat h = hw_h - (hw_h * v);
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y;
- vtx[2] = x; vtx[3] = y + h;
- vtx[4] = x + w; vtx[5] = y + h;
- vtx[6] = x + w; vtx[7] = y;
+ vtx[0] = x; vtx[1] = y + h;
+ vtx[2] = x; vtx[3] = y;
+ vtx[4] = x + w; vtx[5] = y;
+ vtx[6] = x + w; vtx[7] = y + h;
}
};
@@ -1817,10 +1817,10 @@
const GLfloat h = 1.0f;
const GLfloat x = (hw_w - w) * 0.5f;
const GLfloat y = (hw_h - h) * 0.5f;
- vtx[0] = x; vtx[1] = y;
- vtx[2] = x; vtx[3] = y + h;
- vtx[4] = x + w; vtx[5] = y + h;
- vtx[6] = x + w; vtx[7] = y;
+ vtx[0] = x; vtx[1] = y + h;
+ vtx[2] = x; vtx[3] = y;
+ vtx[4] = x + w; vtx[5] = y;
+ vtx[6] = x + w; vtx[7] = y + h;
}
};
@@ -2404,8 +2404,7 @@
const int self_pid = getpid();
if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
// we're called from a different process, do the real check
- if (!checkCallingPermission(
- String16("android.permission.ACCESS_SURFACE_FLINGER")))
+ if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
{
LOGE("Permission Denial: "
"can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
@@ -2463,9 +2462,6 @@
status_t Client::destroySurface(SurfaceID sid) {
return mFlinger->removeSurface(this, sid);
}
-status_t Client::setState(int32_t count, const layer_state_t* states) {
- return mFlinger->setClientState(this, count, states);
-}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index af1ef04..b49fa36 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -20,21 +20,20 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
-#include <binder/IMemory.h>
-#include <binder/Permission.h>
#include <binder/BinderService.h>
+#include <binder/IMemory.h>
#include <ui/PixelFormat.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceComposerClient.h>
-#include <surfaceflinger/IGraphicBufferAlloc.h>
#include "Barrier.h"
#include "Layer.h"
@@ -71,14 +70,12 @@
sp<LayerBaseClient> getLayerUser(int32_t i) const;
private:
-
// ISurfaceComposerClient interface
virtual sp<ISurface> createSurface(
surface_data_t* params, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
- virtual status_t setState(int32_t count, const layer_state_t* states);
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
@@ -169,8 +166,7 @@
virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
- virtual void openGlobalTransaction();
- virtual void closeGlobalTransaction();
+ virtual void setTransactionState(const Vector<ComposerState>& state);
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
@@ -221,8 +217,7 @@
status_t removeSurface(const sp<Client>& client, SurfaceID sid);
status_t destroySurface(const wp<LayerBaseClient>& layer);
- status_t setClientState(const sp<Client>& client,
- int32_t count, const layer_state_t* states);
+ uint32_t setClientStateLocked(const sp<Client>& client, const layer_state_t& s);
class LayerVector : public SortedVector< sp<LayerBase> > {
public:
@@ -338,7 +333,6 @@
mutable Mutex mStateLock;
State mCurrentState;
volatile int32_t mTransactionFlags;
- volatile int32_t mTransactionCount;
Condition mTransactionCV;
SortedVector< sp<LayerBase> > mLayerPurgatory;
bool mResizeTransationPending;
@@ -353,11 +347,7 @@
surface_flinger_cblk_t* mServerCblk;
GLuint mWormholeTexName;
nsecs_t mBootTime;
- Permission mHardwareTest;
- Permission mAccessSurfaceFlinger;
- Permission mReadFramebuffer;
- Permission mDump;
-
+
// Can only accessed from the main thread, these members
// don't need synchronization
State mDrawingState;
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 18c54b3..56b2a8f 100644
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
@@ -43,9 +43,9 @@
PIXEL_FORMAT_RGB_565);
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surface->setLayer(100000);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
Surface::SurfaceInfo info;
surface->lock(&info);
@@ -57,9 +57,9 @@
android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h);
surface->unlockAndPost();
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surface->setSize(320, 240);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
IPCThreadState::self()->joinThreadPool();
diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp
index 5265f91..8e1c3fe 100644
--- a/services/surfaceflinger/tests/surface/surface.cpp
+++ b/services/surfaceflinger/tests/surface/surface.cpp
@@ -39,9 +39,9 @@
sp<SurfaceControl> surfaceControl = client->createSurface(
getpid(), 0, 160, 240, PIXEL_FORMAT_RGB_565);
- client->openTransaction();
+ SurfaceComposerClient::openGlobalTransaction();
surfaceControl->setLayer(100000);
- client->closeTransaction();
+ SurfaceComposerClient::closeGlobalTransaction();
// pretend it went cross-process
Parcel parcel;
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_extended b/services/tests/servicestests/res/raw/xt_qtaguid_extended
new file mode 100644
index 0000000..5bef3dd
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_extended
@@ -0,0 +1,3 @@
+acct_tag_hex uid_tag_int iface rx_bytes rx_packets tx_bytes tx_packets teleported_goats
+0x0 1000 test0 1024 10 2048 20 2716057
+0x0000F00D00000000 1000 test0 512 5 512 5 3370318
diff --git a/services/tests/servicestests/res/raw/xt_qtaguid_typical b/services/tests/servicestests/res/raw/xt_qtaguid_typical
new file mode 100644
index 0000000..7c4f04e
--- /dev/null
+++ b/services/tests/servicestests/res/raw/xt_qtaguid_typical
@@ -0,0 +1,32 @@
+idx iface acct_tag_hex uid_tag_int rx_bytes tx_bytes
+1 wlan0 0x0 0 14615 4270
+2 wlan0 0x0 1000 5175 915
+3 wlan0 0x0 1021 3381 903
+4 wlan0 0x0 10004 333821 53558
+5 wlan0 0x0 10010 4888 37363
+6 wlan0 0x0 10013 52 104
+7 wlan0 0x74182ada00000000 10004 18725 1066
+8 rmnet0 0x0 0 301274 30244
+9 rmnet0 0x0 1000 304 441
+10 rmnet0 0x0 1013 2880 2272
+11 rmnet0 0x0 1021 31407 8430
+12 rmnet0 0x0 10003 32665 3814
+13 rmnet0 0x0 10004 2373141 420112
+14 rmnet0 0x0 10010 870370 1111727
+15 rmnet0 0x0 10013 240 240
+16 rmnet0 0x0 10016 16703 13512
+17 rmnet0 0x0 10017 3990 3269
+18 rmnet0 0x0 10018 474504 14516062
+19 rmnet0 0x0 10019 782804 71077
+20 rmnet0 0x0 10022 70671 49684
+21 rmnet0 0x0 10029 5785354 397159
+22 rmnet0 0x0 10033 2102 1686
+23 rmnet0 0x0 10034 15495464 227694
+24 rmnet0 0x0 10037 31184994 684122
+25 rmnet0 0x0 10051 298687 113485
+26 rmnet0 0x0 10056 29504 20669
+27 rmnet0 0x0 10069 683 596
+28 rmnet0 0x0 10072 34051 12453
+29 rmnet0 0x0 10077 7025393 213866
+30 rmnet0 0x0 10081 354 1178
+31 rmnet0 0x74182ada00000000 10037 28507378 437004
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
new file mode 100644
index 0000000..ac7cb5a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.server;
+
+import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+import static com.android.server.NetworkManagementSocketTagger.tagToKernel;
+
+import android.content.res.Resources;
+import android.net.NetworkStats;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.frameworks.servicestests.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+/**
+ * Tests for {@link NetworkManagementService}.
+ */
+@LargeTest
+public class NetworkManagementServiceTest extends AndroidTestCase {
+ private File mTestProc;
+ private NetworkManagementService mService;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mTestProc = getContext().getFilesDir();
+ mService = NetworkManagementService.createForTest(mContext, mTestProc);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mService = null;
+
+ super.tearDown();
+ }
+
+ public void testNetworkStatsDetail() throws Exception {
+ stageFile(R.raw.xt_qtaguid_typical, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+ final NetworkStats stats = mService.getNetworkStatsDetail();
+ assertEquals(31, stats.size);
+ assertStatsEntry(stats, "wlan0", 0, 0, 14615L, 4270L);
+ assertStatsEntry(stats, "wlan0", 10004, 0, 333821L, 53558L);
+ assertStatsEntry(stats, "wlan0", 10004, 1947740890, 18725L, 1066L);
+ assertStatsEntry(stats, "rmnet0", 10037, 0, 31184994L, 684122L);
+ assertStatsEntry(stats, "rmnet0", 10037, 1947740890, 28507378L, 437004L);
+ }
+
+ public void testNetworkStatsDetailExtended() throws Exception {
+ stageFile(R.raw.xt_qtaguid_extended, new File(mTestProc, "net/xt_qtaguid/stats"));
+
+ final NetworkStats stats = mService.getNetworkStatsDetail();
+ assertEquals(2, stats.size);
+ assertStatsEntry(stats, "test0", 1000, 0, 1024L, 2048L);
+ assertStatsEntry(stats, "test0", 1000, 0xF00D, 512L, 512L);
+ }
+
+ public void testKernelTags() throws Exception {
+ assertEquals("0", tagToKernel(0x0));
+ assertEquals("214748364800", tagToKernel(0x32));
+ assertEquals("9223372032559808512", tagToKernel(Integer.MAX_VALUE));
+ assertEquals("0", tagToKernel(Integer.MIN_VALUE));
+ assertEquals("9223369837831520256", tagToKernel(Integer.MIN_VALUE - 512));
+
+ assertEquals(0, kernelToTag("0x0000000000000000"));
+ assertEquals(0x32, kernelToTag("0x0000003200000000"));
+ assertEquals(2147483647, kernelToTag("0x7fffffff00000000"));
+ assertEquals(0, kernelToTag("0x0000000000000000"));
+ assertEquals(2147483136, kernelToTag("0x7FFFFE0000000000"));
+
+ }
+
+ /**
+ * Copy a {@link Resources#openRawResource(int)} into {@link File} for
+ * testing purposes.
+ */
+ private void stageFile(int rawId, File file) throws Exception {
+ new File(file.getParent()).mkdirs();
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = getContext().getResources().openRawResource(rawId);
+ out = new FileOutputStream(file);
+ Streams.copy(in, out);
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ }
+ }
+
+ private static void assertStatsEntry(
+ NetworkStats stats, String iface, int uid, int tag, long rx, long tx) {
+ final int i = stats.findIndex(iface, uid, tag);
+ assertEquals(rx, stats.rx[i]);
+ assertEquals(tx, stats.tx[i]);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index edccf6c..b4ac987 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,16 +16,20 @@
package com.android.server;
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
+import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.TEMPLATE_WIFI;
+import static android.net.NetworkTemplate.MATCH_WIFI;
import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
@@ -37,7 +41,9 @@
import android.app.INotificationManager;
import android.app.IProcessObserver;
import android.content.Intent;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.Signature;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkPolicyListener;
@@ -48,7 +54,9 @@
import android.net.NetworkPolicy;
import android.net.NetworkState;
import android.net.NetworkStats;
+import android.net.NetworkTemplate;
import android.os.Binder;
+import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.test.AndroidTestCase;
import android.test.mock.MockPackageManager;
@@ -58,12 +66,17 @@
import android.util.TrustedTime;
import com.android.server.net.NetworkPolicyManagerService;
+import com.google.common.util.concurrent.AbstractFuture;
import org.easymock.Capture;
import org.easymock.EasyMock;
+import org.easymock.IAnswer;
import java.io.File;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Tests for {@link NetworkPolicyManagerService}.
@@ -75,12 +88,15 @@
private static final long TEST_START = 1194220800000L;
private static final String TEST_IFACE = "test0";
+ private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
+
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
private IActivityManager mActivityManager;
private IPowerManager mPowerManager;
private INetworkStatsService mStatsService;
+ private INetworkManagementService mNetworkManagement;
private INetworkPolicyListener mPolicyListener;
private TrustedTime mTime;
private IConnectivityManager mConnManager;
@@ -111,22 +127,40 @@
public String[] getPackagesForUid(int uid) {
return new String[] { "com.example" };
}
+
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags) {
+ final PackageInfo info = new PackageInfo();
+ final Signature signature;
+ if ("android".equals(packageName)) {
+ signature = new Signature("F00D");
+ } else {
+ signature = new Signature("DEAD");
+ }
+ info.signatures = new Signature[] { signature };
+ return info;
+ }
};
}
};
mPolicyDir = getContext().getFilesDir();
+ for (File file : mPolicyDir.listFiles()) {
+ file.delete();
+ }
mActivityManager = createMock(IActivityManager.class);
mPowerManager = createMock(IPowerManager.class);
mStatsService = createMock(INetworkStatsService.class);
+ mNetworkManagement = createMock(INetworkManagementService.class);
mPolicyListener = createMock(INetworkPolicyListener.class);
mTime = createMock(TrustedTime.class);
mConnManager = createMock(IConnectivityManager.class);
mNotifManager = createMock(INotificationManager.class);
mService = new NetworkPolicyManagerService(
- mServiceContext, mActivityManager, mPowerManager, mStatsService, mTime, mPolicyDir);
+ mServiceContext, mActivityManager, mPowerManager, mStatsService,
+ mNetworkManagement, mTime, mPolicyDir);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
@@ -145,6 +179,9 @@
expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
expectTime(System.currentTimeMillis());
+ // default behavior is background data enabled
+ expect(mConnManager.getBackgroundDataSetting()).andReturn(true);
+
replay();
mService.systemReady();
verifyAndReset();
@@ -182,7 +219,7 @@
final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
- mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+ mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
backgroundChanged.get();
}
@@ -221,81 +258,123 @@
}
public void testScreenChangesRules() throws Exception {
- // push strict policy for foreground uid, verify ALLOW rule
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ Future<Void> future;
+
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+ future.get();
+ verifyAndReset();
+
+ // push strict policy for foreground uid, verify ALLOW rule
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
verifyAndReset();
// now turn screen off and verify REJECT rule
expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
- expectRulesChanged(UID_A, RULE_REJECT_PAID);
+ expectSetUidNetworkRules(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+ future.get();
verifyAndReset();
// and turn screen back on, verify ALLOW rule restored
expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+ future.get();
verifyAndReset();
}
public void testPolicyNone() throws Exception {
+ Future<Void> future;
+
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ future.get();
+ verifyAndReset();
+
// POLICY_NONE should RULE_ALLOW in foreground
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mService.setUidPolicy(UID_A, POLICY_NONE);
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ future.get();
verifyAndReset();
// POLICY_NONE should RULE_ALLOW in background
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ future.get();
verifyAndReset();
}
public void testPolicyReject() throws Exception {
+ Future<Void> future;
+
// POLICY_REJECT should RULE_ALLOW in background
- expectRulesChanged(UID_A, RULE_REJECT_PAID);
+ expectSetUidNetworkRules(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+ mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
verifyAndReset();
// POLICY_REJECT should RULE_ALLOW in foreground
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ future.get();
verifyAndReset();
// POLICY_REJECT should RULE_REJECT in background
- expectRulesChanged(UID_A, RULE_REJECT_PAID);
+ expectSetUidNetworkRules(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ future.get();
verifyAndReset();
}
public void testPolicyRejectAddRemove() throws Exception {
+ Future<Void> future;
+
// POLICY_NONE should have RULE_ALLOW in background
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
- mService.setUidPolicy(UID_A, POLICY_NONE);
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ mService.setUidPolicy(UID_A, POLICY_NONE);
+ future.get();
verifyAndReset();
// adding POLICY_REJECT should cause RULE_REJECT
- expectRulesChanged(UID_A, RULE_REJECT_PAID);
+ expectSetUidNetworkRules(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
replay();
- mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+ mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
verifyAndReset();
// removing POLICY_REJECT should return us to RULE_ALLOW
- expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
replay();
mService.setUidPolicy(UID_A, POLICY_NONE);
+ future.get();
verifyAndReset();
}
@@ -304,7 +383,7 @@
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
- final NetworkPolicy policy = new NetworkPolicy(TEMPLATE_WIFI, null, 5, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 5, 1024L, 1024L);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -314,7 +393,7 @@
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
- final NetworkPolicy policy = new NetworkPolicy(TEMPLATE_WIFI, null, 20, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 20, 1024L, 1024L);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -324,7 +403,7 @@
final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
- final NetworkPolicy policy = new NetworkPolicy(TEMPLATE_WIFI, null, 30, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -334,7 +413,7 @@
final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
final long expectedCycle = parseTime("2007-03-01T00:00:00.000Z");
- final NetworkPolicy policy = new NetworkPolicy(TEMPLATE_WIFI, null, 30, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(sTemplateWifi, 30, 1024L, 1024L);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -343,6 +422,7 @@
long elapsedRealtime = 0;
NetworkState[] state = null;
NetworkStats stats = null;
+ Future<Void> future;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -353,9 +433,11 @@
state = new NetworkState[] { buildWifi() };
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectTime(TIME_MAR_10 + elapsedRealtime);
+ future = expectMeteredIfacesChanged();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ future.get();
verifyAndReset();
// now change cycle to be on 15th, and test in early march, to verify we
@@ -365,17 +447,42 @@
// pretend that 512 bytes total have happened
stats = new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, 256L, 256L);
- expect(mStatsService.getSummaryForNetwork(TIME_FEB_15, TIME_MAR_10, TEMPLATE_WIFI, null))
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 256L);
+ expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
.andReturn(stats).atLeastOnce();
- // expect that quota remaining should be 1536 bytes
- // TODO: write up NetworkManagementService mock
+ // TODO: consider making strongly ordered mock
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, 1536L);
expectClearNotifications();
+ future = expectMeteredIfacesChanged(TEST_IFACE);
replay();
- setNetworkPolicies(new NetworkPolicy(TEMPLATE_WIFI, null, CYCLE_DAY, 1024L, 2048L));
+ setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
+ future.get();
+ verifyAndReset();
+ }
+
+ public void testUidRemovedPolicyCleared() throws Exception {
+ Future<Void> future;
+
+ // POLICY_REJECT should RULE_REJECT in background
+ expectSetUidNetworkRules(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ replay();
+ mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
+ verifyAndReset();
+
+ // uninstall should clear RULE_REJECT
+ expectSetUidNetworkRules(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ final Intent intent = new Intent(ACTION_UID_REMOVED);
+ intent.putExtra(EXTRA_UID, UID_A);
+ mServiceContext.sendBroadcast(intent);
+ future.get();
verifyAndReset();
}
@@ -410,20 +517,62 @@
expectLastCall().anyTimes();
}
- private void expectRulesChanged(int uid, int policy) throws Exception {
- mPolicyListener.onRulesChanged(eq(uid), eq(policy));
+ private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
+ mNetworkManagement.setInterfaceQuota(iface, quota);
expectLastCall().atLeastOnce();
}
+ private void expectRemoveInterfaceQuota(String iface) throws Exception {
+ mNetworkManagement.removeInterfaceQuota(iface);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
+ throws Exception {
+ mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ expectLastCall().atLeastOnce();
+ }
+
+ private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
+ final FutureAnswer future = new FutureAnswer();
+ mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+ expectLastCall().andAnswer(future);
+ return future;
+ }
+
+ private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
+ final FutureAnswer future = new FutureAnswer();
+ mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+ expectLastCall().andAnswer(future);
+ return future;
+ }
+
+ private static class FutureAnswer extends AbstractFuture<Void> implements IAnswer<Void> {
+ @Override
+ public Void get() throws InterruptedException, ExecutionException {
+ try {
+ return get(5, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Void answer() {
+ set(null);
+ return null;
+ }
+ }
+
private void replay() {
- EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
- mConnManager, mNotifManager);
+ EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+ mNetworkManagement, mTime, mConnManager, mNotifManager);
}
private void verifyAndReset() {
- EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
- mConnManager, mNotifManager);
- EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener, mTime,
- mConnManager, mNotifManager);
+ EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+ mNetworkManagement, mTime, mConnManager, mNotifManager);
+ EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
+ mNetworkManagement, mTime, mConnManager, mNotifManager);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 2457ff3..903f2b0 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -16,16 +16,26 @@
package com.android.server;
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.TEMPLATE_WIFI;
+import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
+import static android.net.NetworkTemplate.MATCH_WIFI;
+import static android.net.TrafficStats.UID_REMOVED;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
+import static com.android.server.net.NetworkStatsService.packUidAndTag;
+import static com.android.server.net.NetworkStatsService.unpackTag;
+import static com.android.server.net.NetworkStatsService.unpackUid;
import static org.easymock.EasyMock.anyLong;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
@@ -44,7 +54,9 @@
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
import android.os.INetworkManagementService;
+import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.TrustedTime;
@@ -66,8 +78,16 @@
private static final String TEST_IFACE = "test0";
private static final long TEST_START = 1194220800000L;
- private static final int TEST_UID_1 = 1001;
- private static final int TEST_UID_2 = 1002;
+ private static final String IMSI_1 = "310004";
+ private static final String IMSI_2 = "310260";
+
+ private static NetworkTemplate sTemplateWifi = new NetworkTemplate(MATCH_WIFI, null);
+ private static NetworkTemplate sTemplateImsi1 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_1);
+ private static NetworkTemplate sTemplateImsi2 = new NetworkTemplate(MATCH_MOBILE_ALL, IMSI_2);
+
+ private static final int UID_RED = 1001;
+ private static final int UID_BLUE = 1002;
+ private static final int UID_GREEN = 1003;
private BroadcastInterceptingContext mServiceContext;
private File mStatsDir;
@@ -118,13 +138,15 @@
mNetManager = null;
mAlarmManager = null;
mTime = null;
+ mSettings = null;
+ mConnManager = null;
mService = null;
super.tearDown();
}
- public void testSummaryStatsWifi() throws Exception {
+ public void testNetworkStatsWifi() throws Exception {
long elapsedRealtime = 0;
// pretend that wifi network comes online; service should ask about full
@@ -138,7 +160,7 @@
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
// verify service has empty history for wifi
- assertNetworkTotal(TEMPLATE_WIFI, 0L, 0L);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L);
verifyAndReset();
// modify some number on wifi, and trigger poll event
@@ -146,14 +168,14 @@
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, 1024L, 2048L));
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
- assertNetworkTotal(TEMPLATE_WIFI, 1024L, 2048L);
+ assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
verifyAndReset();
// and bump forward again, with counters going higher. this is
@@ -162,14 +184,14 @@
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, 4096L, 8192L));
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 8192L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
- assertNetworkTotal(TEMPLATE_WIFI, 4096L, 8192L);
+ assertNetworkTotal(sTemplateWifi, 4096L, 8192L);
verifyAndReset();
}
@@ -189,7 +211,7 @@
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
// verify service has empty history for wifi
- assertNetworkTotal(TEMPLATE_WIFI, 0L, 0L);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L);
verifyAndReset();
// modify some number on wifi, and trigger poll event
@@ -197,19 +219,18 @@
expectTime(TEST_START + elapsedRealtime);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, 1024L, 2048L));
- // TODO: switch these stats to specific iface
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 2048L));
expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2)
- .addEntry(IFACE_ALL, TEST_UID_1, 512L, 256L)
- .addEntry(IFACE_ALL, TEST_UID_2, 128L, 128L));
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 128L));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
- assertNetworkTotal(TEMPLATE_WIFI, 1024L, 2048L);
- assertUidTotal(TEST_UID_1, TEMPLATE_WIFI, 512L, 256L);
- assertUidTotal(TEST_UID_2, TEMPLATE_WIFI, 128L, 128L);
+ assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
+ assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L);
verifyAndReset();
// graceful shutdown system, which should trigger persist of stats, and
@@ -220,7 +241,7 @@
// we persisted them to file.
expectDefaultSettings();
replay();
- assertNetworkTotal(TEMPLATE_WIFI, 0L, 0L);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L);
verifyAndReset();
assertStatsFilesExist(true);
@@ -233,9 +254,9 @@
mService.systemReady();
// after systemReady(), we should have historical stats loaded again
- assertNetworkTotal(TEMPLATE_WIFI, 1024L, 2048L);
- assertUidTotal(TEST_UID_1, TEMPLATE_WIFI, 512L, 256L);
- assertUidTotal(TEST_UID_2, TEMPLATE_WIFI, 128L, 128L);
+ assertNetworkTotal(sTemplateWifi, 1024L, 2048L);
+ assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L);
verifyAndReset();
}
@@ -263,14 +284,14 @@
expectTime(TEST_START + elapsedRealtime);
expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
- .addEntry(TEST_IFACE, UID_ALL, 512L, 512L));
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 512L));
expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify service recorded history
- history = mService.getHistoryForNetwork(TEMPLATE_WIFI);
+ history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
assertEquals(512L, total[0]);
assertEquals(512L, total[1]);
@@ -289,7 +310,7 @@
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
// verify identical stats, but spread across 4 buckets now
- history = mService.getHistoryForNetwork(TEMPLATE_WIFI);
+ history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null));
total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
assertEquals(512L, total[0]);
assertEquals(512L, total[1]);
@@ -299,15 +320,284 @@
}
- private void assertNetworkTotal(int template, long rx, long tx) {
+ public void testUidStatsAcrossNetworks() throws Exception {
+ long elapsedRealtime = 0;
+
+ // pretend first mobile network comes online
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildMobile3gState(IMSI_1));
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ verifyAndReset();
+
+ // create some traffic on first network
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 512L));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3)
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 512L)
+ .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 0L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L);
+ assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
+ assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
+ verifyAndReset();
+
+ // now switch networks; this also tests that we're okay with interfaces
+ // disappearing, to verify we don't count backwards.
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildMobile3gState(IMSI_2));
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+ verifyAndReset();
+
+ // create traffic on second network
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1024L));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1024L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify original history still intact
+ assertNetworkTotal(sTemplateImsi1, 2048L, 512L);
+ assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L);
+ assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L);
+
+ // and verify new history also recorded under different template, which
+ // verifies that we didn't cross the streams.
+ assertNetworkTotal(sTemplateImsi2, 128L, 1024L);
+ assertNetworkTotal(sTemplateWifi, 0L, 0L);
+ assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L);
+ verifyAndReset();
+
+ }
+
+ public void testUidRemovedIsMoved() throws Exception {
+ long elapsedRealtime = 0;
+
+ // pretend that network comes online
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildWifiState());
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ verifyAndReset();
+
+ // create some traffic
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 544L));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 16L, 16L)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 512L)
+ .addEntry(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 16L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify service recorded history
+ assertNetworkTotal(sTemplateWifi, 4128L, 544L);
+ assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L);
+ assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
+ verifyAndReset();
+
+ // now pretend two UIDs are uninstalled, which should migrate stats to
+ // special "removed" bucket.
+ expectDefaultSettings();
+ replay();
+ final Intent intent = new Intent(ACTION_UID_REMOVED);
+ intent.putExtra(EXTRA_UID, UID_BLUE);
+ mServiceContext.sendBroadcast(intent);
+ intent.putExtra(EXTRA_UID, UID_RED);
+ mServiceContext.sendBroadcast(intent);
+
+ // existing uid and total should remain unchanged; but removed UID
+ // should be gone completely.
+ assertNetworkTotal(sTemplateWifi, 4128L, 544L);
+ assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L);
+ assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L);
+ assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L);
+ verifyAndReset();
+
+ }
+
+ public void testUid3g4gCombinedByTemplate() throws Exception {
+ long elapsedRealtime = 0;
+
+ // pretend that network comes online
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildMobile3gState(IMSI_1));
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ verifyAndReset();
+
+ // create some traffic
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 1024L)
+ .addEntry(TEST_IFACE, UID_RED, 0xF00D, 512L, 512L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify service recorded history
+ assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L);
+ verifyAndReset();
+
+ // now switch over to 4g network
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildMobile4gState());
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+ verifyAndReset();
+
+ // create traffic on second network
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 512L, 256L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify that ALL_MOBILE template combines both
+ assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L);
+
+ verifyAndReset();
+
+ }
+
+ public void testPackedUidAndTag() throws Exception {
+ assertEquals(0x0000000000000000L, packUidAndTag(0, 0x0));
+ assertEquals(0x000003E900000000L, packUidAndTag(1001, 0x0));
+ assertEquals(0x000003E90000F00DL, packUidAndTag(1001, 0xF00D));
+
+ long packed;
+ packed = packUidAndTag(Integer.MAX_VALUE, Integer.MIN_VALUE);
+ assertEquals(Integer.MAX_VALUE, unpackUid(packed));
+ assertEquals(Integer.MIN_VALUE, unpackTag(packed));
+
+ packed = packUidAndTag(Integer.MIN_VALUE, Integer.MAX_VALUE);
+ assertEquals(Integer.MIN_VALUE, unpackUid(packed));
+ assertEquals(Integer.MAX_VALUE, unpackTag(packed));
+
+ packed = packUidAndTag(10005, 0xFFFFFFFF);
+ assertEquals(10005, unpackUid(packed));
+ assertEquals(0xFFFFFFFF, unpackTag(packed));
+
+ }
+
+ public void testSummaryForAllUid() throws Exception {
+ long elapsedRealtime = 0;
+
+ // pretend that network comes online
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkState(buildWifiState());
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ verifyAndReset();
+
+ // create some traffic for two apps
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_RED, TAG_NONE, 50L, 50L)
+ .addEntry(TEST_IFACE, UID_RED, 0xF00D, 10L, 10L)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 512L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // verify service recorded history
+ assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L);
+ verifyAndReset();
+
+ // now create more traffic in next hour, but only for one app
+ elapsedRealtime += HOUR_IN_MILLIS;
+ expectTime(TEST_START + elapsedRealtime);
+ expectDefaultSettings();
+ expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime));
+ expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1)
+ .addEntry(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 1024L));
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
+
+ // first verify entire history present
+ NetworkStats stats = mService.getSummaryForAllUid(
+ sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
+ assertEquals(3, stats.size);
+ assertStatsEntry(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 50L);
+ assertStatsEntry(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 10L);
+ assertStatsEntry(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 1024L);
+
+ // now verify that recent history only contains one uid
+ final long currentTime = TEST_START + elapsedRealtime;
+ stats = mService.getSummaryForAllUid(
+ sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
+ assertEquals(1, stats.size);
+ assertStatsEntry(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 512L);
+
+ verifyAndReset();
+ }
+
+ private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) {
final NetworkStatsHistory history = mService.getHistoryForNetwork(template);
final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
assertEquals(rx, total[0]);
assertEquals(tx, total[1]);
}
- private void assertUidTotal(int uid, int template, long rx, long tx) {
- final NetworkStatsHistory history = mService.getHistoryForUid(uid, template);
+ private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) {
+ final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE);
final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null);
assertEquals(rx, total[0]);
assertEquals(tx, total[1]);
@@ -320,6 +610,9 @@
mAlarmManager.setInexactRepeating(
eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
expectLastCall().atLeastOnce();
+
+ mNetManager.setBandwidthControlEnabled(true);
+ expectLastCall().atLeastOnce();
}
private void expectNetworkState(NetworkState... state) throws Exception {
@@ -340,12 +633,14 @@
private void expectSettings(long persistThreshold, long bucketDuration, long maxHistory)
throws Exception {
+ expect(mSettings.getEnabled()).andReturn(true).anyTimes();
expect(mSettings.getPollInterval()).andReturn(HOUR_IN_MILLIS).anyTimes();
expect(mSettings.getPersistThreshold()).andReturn(persistThreshold).anyTimes();
expect(mSettings.getNetworkBucketDuration()).andReturn(bucketDuration).anyTimes();
expect(mSettings.getNetworkMaxHistory()).andReturn(maxHistory).anyTimes();
expect(mSettings.getUidBucketDuration()).andReturn(bucketDuration).anyTimes();
expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes();
+ expect(mSettings.getTagMaxHistory()).andReturn(maxHistory).anyTimes();
expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes();
}
@@ -358,17 +653,26 @@
}
private void assertStatsFilesExist(boolean exist) {
- final File summaryFile = new File(mStatsDir, "netstats.bin");
- final File detailFile = new File(mStatsDir, "netstats_uid.bin");
+ final File networkFile = new File(mStatsDir, "netstats.bin");
+ final File uidFile = new File(mStatsDir, "netstats_uid.bin");
if (exist) {
- assertTrue(summaryFile.exists());
- assertTrue(detailFile.exists());
+ assertTrue(networkFile.exists());
+ assertTrue(uidFile.exists());
} else {
- assertFalse(summaryFile.exists());
- assertFalse(detailFile.exists());
+ assertFalse(networkFile.exists());
+ assertFalse(uidFile.exists());
}
}
+ private static void assertStatsEntry(
+ NetworkStats stats, int i, String iface, int uid, int tag, long rx, long tx) {
+ assertEquals(iface, stats.iface[i]);
+ assertEquals(uid, stats.uid[i]);
+ assertEquals(tag, stats.tag[i]);
+ assertEquals(rx, stats.rx[i]);
+ assertEquals(tx, stats.tx[i]);
+ }
+
private static NetworkState buildWifiState() {
final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null);
info.setDetailedState(DetailedState.CONNECTED, null, null);
@@ -377,6 +681,23 @@
return new NetworkState(info, prop, null);
}
+ private static NetworkState buildMobile3gState(String subscriberId) {
+ final NetworkInfo info = new NetworkInfo(
+ TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UMTS, null, null);
+ info.setDetailedState(DetailedState.CONNECTED, null, null);
+ final LinkProperties prop = new LinkProperties();
+ prop.setInterfaceName(TEST_IFACE);
+ return new NetworkState(info, prop, null, subscriberId);
+ }
+
+ private static NetworkState buildMobile4gState() {
+ final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
+ info.setDetailedState(DetailedState.CONNECTED, null, null);
+ final LinkProperties prop = new LinkProperties();
+ prop.setInterfaceName(TEST_IFACE);
+ return new NetworkState(info, prop, null);
+ }
+
private static NetworkStats buildEmptyStats(long elapsedRealtime) {
return new NetworkStats(elapsedRealtime, 0);
}
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index 30afdd8..2f275c3 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -289,7 +289,7 @@
public void expectGetInterfaceCounter(long rx, long tx) throws Exception {
// TODO: provide elapsedRealtime mock to match TimeAuthority
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- stats.addEntry(TEST_IFACE, NetworkStats.UID_ALL, rx, tx);
+ stats.addEntry(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, tx);
expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce();
}
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index ffabb7b..dea67f3 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -94,6 +94,9 @@
*/
public PhoneNumberFormattingTextWatcher(String countryCode) {
if (countryCode == null) throw new IllegalArgumentException();
+ // TODO: remove this once CountryDetector.detectCountry().getCountryIso() is fixed to always
+ // return uppercase. Tracked at b/4941319.
+ countryCode = countryCode.toUpperCase(Locale.ENGLISH);
mFormatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(countryCode);
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 184d665..66120a1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -191,10 +191,6 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
public String getDeviceId() {
- if (!isVoiceCapable()) {
- return null;
- }
-
try {
return getSubscriberInfo().getDeviceId();
} catch (RemoteException ex) {
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 496c43c..a52f1ca 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -16,8 +16,6 @@
package com.android.internal.telephony;
-import android.app.PendingIntent;
-
import android.util.Log;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -49,8 +47,6 @@
String mReason;
- PendingIntent mReconnectIntent;
-
/**
* user/app requested connection on this APN
*/
@@ -89,6 +85,11 @@
}
public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+ if (dcac != null) {
+ dcac.addApnContextSync(this);
+ } else {
+ if (mDataConnectionAc != null) mDataConnectionAc.removeApnContextSync(this);
+ }
mDataConnectionAc = dcac;
}
@@ -164,16 +165,6 @@
return mReason;
}
- public synchronized void setReconnectIntent(PendingIntent intent) {
- if (DBG)
- log("set ReconnectIntent for type " + mApnType);
- mReconnectIntent = intent;
- }
-
- public synchronized PendingIntent getReconnectIntent() {
- return mReconnectIntent;
- }
-
public boolean isReady() {
return mDataEnabled.get() && mDependencyMet.get();
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 457fa7aa..ab93e2a 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -30,8 +30,8 @@
import android.text.TextUtils;
import android.util.Log;
+import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
import com.google.i18n.phonenumbers.NumberParseException;
-import com.google.i18n.phonenumbers.PhoneNumberOfflineGeocoder;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
@@ -526,8 +526,20 @@
+ countryIso);
}
+ // Temp workaround: The current libphonenumber library requires
+ // the countryIso to be uppercase (e.g. "US") but the
+ // detector.detectCountry().getCountryIso() call currently returns
+ // "us". Passing "us" to util.parse() will just result in a
+ // NumberParseException.
+ // So force the countryIso to uppercase for now.
+ // TODO: remove this once getCountryIso() is fixed to always
+ // return uppercase.
+ countryIso = countryIso.toUpperCase();
+
PhoneNumber pn = null;
try {
+ if (VDBG) Log.v(TAG, "parsing '" + number
+ + "' for countryIso '" + countryIso + "'...");
pn = util.parse(number, countryIso);
if (VDBG) Log.v(TAG, "- parsed number: " + pn);
} catch (NumberParseException e) {
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index bbd4232..2e8a742 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -51,6 +51,12 @@
private CallerInfoAsyncQueryHandler mHandler;
+ // If the CallerInfo query finds no contacts, should we use the
+ // PhoneNumberOfflineGeocoder to look up a "geo description"?
+ // (TODO: This could become a flag in config.xml if it ever needs to be
+ // configured on a per-product basis.)
+ private static final boolean ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION = true;
+
/**
* Interface for a CallerInfoAsyncQueryHandler result return.
*/
@@ -242,22 +248,25 @@
}
// Final step: look up the geocoded description.
- //
- // For now, do this only if we *don't* have a valid name (i.e. if
- // no contacts matched the phone number of the incoming call),
- // since that's the only case where the incoming-call UI cares
- // about this field.
- // (TODO: But if we ever want the UI to show the geoDescription
- // even when we *do* match a contact, we'll need to either call
- // updateGeoDescription() unconditionally here, or possibly add a
- // new parameter to CallerInfoAsyncQuery.startQuery() to force
- // the geoDescription field to be populated.)
- if (TextUtils.isEmpty(mCallerInfo.name)) {
- // Actually when no contacts match the incoming phone number,
- // the CallerInfo object is totally blank here (i.e. no name
- // *or* phoneNumber). So we need to pass in cw.number as
- // a fallback number.
- mCallerInfo.updateGeoDescription(mQueryContext, cw.number);
+ if (ENABLE_UNKNOWN_NUMBER_GEO_DESCRIPTION) {
+ // Note we do this only if we *don't* have a valid name (i.e. if
+ // no contacts matched the phone number of the incoming call),
+ // since that's the only case where the incoming-call UI cares
+ // about this field.
+ //
+ // (TODO: But if we ever want the UI to show the geoDescription
+ // even when we *do* match a contact, we'll need to either call
+ // updateGeoDescription() unconditionally here, or possibly add a
+ // new parameter to CallerInfoAsyncQuery.startQuery() to force
+ // the geoDescription field to be populated.)
+
+ if (TextUtils.isEmpty(mCallerInfo.name)) {
+ // Actually when no contacts match the incoming phone number,
+ // the CallerInfo object is totally blank here (i.e. no name
+ // *or* phoneNumber). So we need to pass in cw.number as
+ // a fallback number.
+ mCallerInfo.updateGeoDescription(mQueryContext, cw.number);
+ }
}
// Use the number entered by the user for display.
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index f5651e0..fba3184 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -47,6 +47,7 @@
public String [] addresses = new String[0];
public String [] dnses = new String[0];
public String[] gateways = new String[0];
+ public int suggestedRetryTime = -1;
/**
* Class returned by onSetupConnectionCompleted.
@@ -77,6 +78,7 @@
sb.append("DataCallState: {")
.append("version=").append(version)
.append(" status=").append(status)
+ .append(" retry=").append(suggestedRetryTime)
.append(" cid=").append(cid)
.append(" active=").append(active)
.append(" type=").append(type)
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 5c030fd..5c84fdc 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -22,6 +22,7 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import android.app.PendingIntent;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
@@ -35,8 +36,10 @@
import android.os.SystemProperties;
import android.text.TextUtils;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -68,6 +71,8 @@
protected static int mCount;
protected AsyncChannel mAc;
+ private List<ApnContext> mApnList = null;
+ PendingIntent mReconnectIntent = null;
/**
* Used internally for saving connecting parameters.
@@ -182,6 +187,18 @@
}
}
+ public static class CallSetupException extends Exception {
+ private int mRetryOverride = -1;
+
+ CallSetupException (int retryOverride) {
+ mRetryOverride = retryOverride;
+ }
+
+ public int getRetryOverride() {
+ return mRetryOverride;
+ }
+ }
+
// ***** Event codes for driving the state machine
protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
protected static final int EVENT_CONNECT = BASE + 0;
@@ -205,6 +222,7 @@
protected long createTime;
protected long lastFailTime;
protected FailCause lastFailCause;
+ protected int mRetryOverride = -1;
protected static final String NULL_IP = "0.0.0.0";
private int mRefCount;
Object userData;
@@ -237,6 +255,8 @@
addState(mDisconnectingState, mDefaultState);
addState(mDisconnectingErrorCreatingConnection, mDefaultState);
setInitialState(mInactiveState);
+
+ mApnList = new ArrayList<ApnContext>();
if (DBG) log("DataConnection constructor X");
}
@@ -288,7 +308,8 @@
} else {
lastFailCause = cause;
lastFailTime = timeStamp;
- AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception());
+ AsyncResult.forMessage(connectionCompletedMsg, cause,
+ new CallSetupException(mRetryOverride));
}
if (DBG) log("notifyConnectionCompleted at " + timeStamp + " cause=" + cause);
@@ -430,6 +451,7 @@
createTime = -1;
lastFailTime = -1;
lastFailCause = FailCause.NONE;
+ mRetryOverride = -1;
mRefCount = 0;
mLinkProperties = new LinkProperties();
@@ -482,6 +504,15 @@
return result;
}
+ private int getSuggestedRetryTime(AsyncResult ar) {
+ int retry = -1;
+ if (ar.exception == null) {
+ DataCallState response = (DataCallState) ar.result;
+ retry = response.suggestedRetryTime;
+ }
+ return retry;
+ }
+
private DataCallState.SetupResult setLinkProperties(DataCallState response,
LinkProperties lp) {
// Check if system property dns usable
@@ -638,7 +669,41 @@
mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
break;
}
-
+ case DataConnectionAc.REQ_ADD_APNCONTEXT: {
+ ApnContext apnContext = (ApnContext) msg.obj;
+ if (VDBG) log("REQ_ADD_APNCONTEXT apn=" + apnContext.getApnType());
+ if (!mApnList.contains(apnContext)) {
+ mApnList.add(apnContext);
+ }
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_ADD_APNCONTEXT);
+ break;
+ }
+ case DataConnectionAc.REQ_REMOVE_APNCONTEXT: {
+ ApnContext apnContext = (ApnContext) msg.obj;
+ if (VDBG) log("REQ_REMOVE_APNCONTEXT apn=" + apnContext.getApnType());
+ mApnList.remove(apnContext);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_REMOVE_APNCONTEXT);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNCONTEXT_LIST: {
+ if (VDBG) log("REQ_GET_APNCONTEXT_LIST num in list=" + mApnList.size());
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNCONTEXT_LIST,
+ new ArrayList(mApnList));
+ break;
+ }
+ case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
+ PendingIntent intent = (PendingIntent) msg.obj;
+ if (VDBG) log("REQ_SET_RECONNECT_INTENT");
+ mReconnectIntent = intent;
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_RECONNECT_INTENT);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_RECONNECT_INTENT: {
+ if (VDBG) log("REQ_GET_RECONNECT_INTENT");
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_RECONNECT_INTENT,
+ mReconnectIntent);
+ break;
+ }
case EVENT_CONNECT:
if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
ConnectionParams cp = (ConnectionParams) msg.obj;
@@ -685,10 +750,12 @@
private FailCause mFailCause = null;
private DisconnectParams mDisconnectParams = null;
- public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
+ public void setEnterNotificationParams(ConnectionParams cp, FailCause cause,
+ int retryOverride) {
if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
mConnectionParams = cp;
mFailCause = cause;
+ mRetryOverride = retryOverride;
}
public void setEnterNotificationParams(DisconnectParams dp) {
@@ -808,7 +875,7 @@
// Vendor ril rejected the command and didn't connect.
// Transition to inactive but send notifications after
// we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause, -1);
transitionTo(mInactiveState);
break;
case ERR_UnacceptableParameter:
@@ -823,7 +890,8 @@
break;
case ERR_RilError:
// Request failed and mFailCause has the reason
- mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
+ getSuggestedRetryTime(ar));
transitionTo(mInactiveState);
break;
case ERR_Stale:
@@ -848,8 +916,8 @@
}
// Transition to inactive but send notifications after
// we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp, cause);
- transitionTo(mInactiveState);
+ mInactiveState.setEnterNotificationParams(cp, cause, -1);
+ transitionTo(mInactiveState);
} else {
if (DBG) {
log("DcActivatingState EVENT_GET_LAST_FAIL_DONE is stale cp.tag="
@@ -1016,7 +1084,7 @@
// Transition to inactive but send notifications after
// we've entered the mInactive state.
mInactiveState.setEnterNotificationParams(cp,
- FailCause.UNACCEPTABLE_NETWORK_PARAMETER);
+ FailCause.UNACCEPTABLE_NETWORK_PARAMETER, -1);
transitionTo(mInactiveState);
} else {
if (DBG) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
index 62b90ae..309dbed6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionAc.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -19,11 +19,15 @@
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import android.app.PendingIntent;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.ProxyProperties;
import android.os.Message;
+import java.util.ArrayList;
+import java.util.Collection;
+
/**
* AsyncChannel to a DataConnection
*/
@@ -62,6 +66,21 @@
public static final int REQ_GET_REFCOUNT = BASE + 16;
public static final int RSP_GET_REFCOUNT = BASE + 17;
+ public static final int REQ_ADD_APNCONTEXT = BASE + 18;
+ public static final int RSP_ADD_APNCONTEXT = BASE + 19;
+
+ public static final int REQ_REMOVE_APNCONTEXT = BASE + 20;
+ public static final int RSP_REMOVE_APNCONTEXT = BASE + 21;
+
+ public static final int REQ_GET_APNCONTEXT_LIST = BASE + 22;
+ public static final int RSP_GET_APNCONTEXT_LIST = BASE + 23;
+
+ public static final int REQ_SET_RECONNECT_INTENT = BASE + 24;
+ public static final int RSP_SET_RECONNECT_INTENT = BASE + 25;
+
+ public static final int REQ_GET_RECONNECT_INTENT = BASE + 26;
+ public static final int RSP_GET_RECONNECT_INTENT = BASE + 27;
+
/**
* enum used to notify action taken or necessary to be
* taken after the link property is changed.
@@ -371,6 +390,150 @@
}
}
+ /**
+ * Request to add ApnContext association.
+ * Response RSP_ADD_APNCONTEXT when complete.
+ */
+ public void reqAddApnContext(ApnContext apnContext) {
+ Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+ if (DBG) log("reqAddApnContext");
+ }
+
+ /**
+ * Add ApnContext association synchronoulsy.
+ *
+ * @param ApnContext to associate
+ */
+ public void addApnContextSync(ApnContext apnContext) {
+ Message response = sendMessageSynchronously(REQ_ADD_APNCONTEXT, apnContext);
+ if ((response != null) && (response.what == RSP_ADD_APNCONTEXT)) {
+ if (DBG) log("addApnContext ok");
+ } else {
+ log("addApnContext error response=" + response);
+ }
+ }
+
+ /**
+ * Request to remove ApnContext association.
+ * Response RSP_REMOVE_APNCONTEXT when complete.
+ */
+ public void reqRemomveApnContext(ApnContext apnContext) {
+ Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+ if (DBG) log("reqRemomveApnContext");
+ }
+
+ /**
+ * Remove ApnContext associateion.
+ *
+ * @param ApnContext to dissociate
+ */
+ public void removeApnContextSync(ApnContext apnContext) {
+ Message response = sendMessageSynchronously(REQ_REMOVE_APNCONTEXT, apnContext);
+ if ((response != null) && (response.what == RSP_REMOVE_APNCONTEXT)) {
+ if (DBG) log("removeApnContext ok");
+ } else {
+ log("removeApnContext error response=" + response);
+ }
+ }
+
+ /**
+ * Request to retrive ApnContext List associated with DC.
+ * Response RSP_GET_APNCONTEXT_LIST when complete.
+ */
+ public void reqGetApnList(ApnContext apnContext) {
+ Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+ if (DBG) log("reqGetApnList");
+ }
+
+ /**
+ * Retrieve Collection of ApnContext from the response message.
+ *
+ * @param Message sent from DC in response to REQ_GET_APNCONTEXT_LIST.
+ * @return Collection of ApnContext
+ */
+ public Collection<ApnContext> rspApnList(Message response) {
+ Collection<ApnContext> retVal = (Collection<ApnContext>)response.obj;
+ if (retVal == null) retVal = new ArrayList<ApnContext>();
+ return retVal;
+ }
+
+ /**
+ * Retrieve collection of ApnContext currently associated with
+ * the DataConnectionA synchronously.
+ *
+ * @return Collection of ApnContext
+ */
+ public Collection<ApnContext> getApnListSync() {
+ Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
+ if ((response != null) && (response.what == RSP_GET_APNCONTEXT_LIST)) {
+ if (DBG) log("getApnList ok");
+ return rspApnList(response);
+ } else {
+ log("getApnList error response=" + response);
+ // return dummy list with no entry
+ return new ArrayList<ApnContext>();
+ }
+ }
+
+ /**
+ * Request to set Pending ReconnectIntent to DC.
+ * Response RSP_SET_RECONNECT_INTENT when complete.
+ */
+ public void reqSetReconnectIntent(PendingIntent intent) {
+ Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+ if (DBG) log("reqSetReconnectIntent");
+ }
+
+ /**
+ * Set pending reconnect intent to DC synchronously.
+ *
+ * @param PendingIntent to set.
+ */
+ public void setReconnectIntentSync(PendingIntent intent) {
+ Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
+ if ((response != null) && (response.what == RSP_SET_RECONNECT_INTENT)) {
+ if (DBG) log("setReconnectIntent ok");
+ } else {
+ log("setReconnectIntent error response=" + response);
+ }
+ }
+
+ /**
+ * Request to get Pending ReconnectIntent to DC.
+ * Response RSP_GET_RECONNECT_INTENT when complete.
+ */
+ public void reqGetReconnectIntent() {
+ Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+ if (DBG) log("reqGetReconnectIntent");
+ }
+
+ /**
+ * Retrieve reconnect intent from response message from DC.
+ *
+ * @param Message which contains the reconnect intent.
+ * @return PendingIntent from the response.
+ */
+ public PendingIntent rspReconnectIntent(Message response) {
+ PendingIntent retVal = (PendingIntent) response.obj;
+ return retVal;
+ }
+
+ /**
+ * Retrieve reconnect intent currently set in DC synchronously.
+ *
+ * @return PendingIntent reconnect intent current ly set in DC
+ */
+ public PendingIntent getReconnectIntentSync() {
+ Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
+ if ((response != null) && (response.what == RSP_GET_RECONNECT_INTENT)) {
+ if (DBG) log("getReconnectIntent ok");
+ return rspReconnectIntent(response);
+ } else {
+ log("getReconnectIntent error response=" + response);
+ return null;
+ }
+ }
+
private void log(String s) {
android.util.Log.d(mLogTag, "DataConnectionAc " + s);
}
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 5fef6de..9763265 100644
--- a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -112,7 +112,7 @@
*/
public void sendText(String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- mPhone.getContext().enforceCallingPermission(
+ mPhone.getContext().enforceCallingOrSelfPermission(
"android.permission.SEND_SMS",
"Sending SMS message");
if (Log.isLoggable("SMS", Log.VERBOSE)) {
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 76f1ab7..c6ed405 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -3009,6 +3009,7 @@
}
} else {
dataCall.status = p.readInt();
+ dataCall.suggestedRetryTime = p.readInt();
dataCall.cid = p.readInt();
dataCall.active = p.readInt();
dataCall.type = p.readString();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 6a95b67..a31b704 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -129,6 +129,12 @@
super.setSystemLocale(language, country, false);
}
+ // return IMSI from USIM as subscriber ID.
+ @Override
+ public String getSubscriberId() {
+ return mIccRecords.getIMSI();
+ }
+
@Override
protected void log(String s) {
if (DBG)
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 19c06f6..67f5158 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -68,7 +68,9 @@
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
import java.util.Map;
import java.util.HashMap;
@@ -123,14 +125,20 @@
if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
- ApnContext apnContext = mApnContexts.get(type);
- if (apnContext != null) {
- apnContext.setReason(reason);
- if (apnContext.getState() == State.FAILED) {
- apnContext.setState(State.IDLE);
+ int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
+
+ DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
+
+ if (dcac != null) {
+ for (ApnContext apnContext : dcac.getApnListSync()) {
+ apnContext.setReason(reason);
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
}
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+ // Alram had expired. Clear pending intent recorded on the DataConnection.
+ dcac.setReconnectIntentSync(null);
}
}
@@ -548,6 +556,9 @@
if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll();
notifyDataConnection(Phone.REASON_DATA_ATTACHED);
+ } else {
+ // update APN availability so that APN can be enabled.
+ notifyDataAvailability(Phone.REASON_DATA_ATTACHED);
}
setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
@@ -589,17 +600,25 @@
}
private void setupDataOnReadyApns(String reason) {
+ // Stop reconnect alarms on all data connections pending
+ // retry. Reset ApnContext state to IDLE.
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.getReconnectIntentSync() != null) {
+ cancelReconnectAlarm(dcac);
+ if (dcac.dataConnection != null) {
+ dcac.dataConnection.resetRetryCount();
+ }
+
+ Collection<ApnContext> apnList = dcac.getApnListSync();
+ for (ApnContext apnContext : apnList) {
+ apnContext.setState(State.IDLE);
+ }
+ }
+ }
+
// Only check for default APN state
for (ApnContext apnContext : mApnContexts.values()) {
if (apnContext.isReady()) {
- if (apnContext.getState() == State.FAILED) {
- cleanApnContextBeforeRestart(apnContext);
- if (apnContext.getDataConnection() != null) {
- apnContext.getDataConnection().resetRetryCount();
- }
- }
- // Do not start ApnContext in SCANNING state
- // FAILED state must be reset to IDLE by now
if (apnContext.getState() == State.IDLE) {
apnContext.setReason(reason);
trySetupData(apnContext);
@@ -749,53 +768,70 @@
if (DBG) {
log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
}
- if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
- // if the request is tearDown and ApnContext does not hold an active connection,
- // we're ok to return here.
- return;
- }
-
DataConnectionAc dcac = apnContext.getDataConnectionAc();
- if (tearDown && (dcac != null)) {
- if (DBG) log("cleanUpConnection: tearing down");
- Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
- apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
- apnContext.setState(State.DISCONNECTING);
+ if (tearDown) {
+ boolean isConnected = (apnContext.getState() != State.IDLE
+ && apnContext.getState() != State.FAILED);
+ if (!isConnected) {
+ // The request is tearDown and but ApnContext is not connected.
+ // If apnContext is not enabled anymore, break the linkage to the DCAC/DC.
+ apnContext.setState(State.IDLE);
+ if (!apnContext.isReady()) {
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ }
+ } else {
+ // Connection is still there. Try to clean up.
+ if (dcac != null) {
+ if (apnContext.getState() != State.DISCONNECTING) {
+ if (DBG) log("cleanUpConnection: tearing down");
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+ apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+ apnContext.setState(State.DISCONNECTING);
+ } else {
+ // apn is connected but no reference to dcac.
+ // Should not be happen, but reset the state in case.
+ apnContext.setState(State.IDLE);
+ mPhone.notifyDataConnection(apnContext.getReason(),
+ apnContext.getApnType());
+ }
+ }
+ }
} else {
+ // force clean up the data connection.
if (dcac != null) dcac.resetSync();
apnContext.setState(State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
}
+
+ // make sure reconnection alarm is cleaned up if there is no ApnContext
+ // associated to the connection.
+ if (dcac != null) {
+ Collection<ApnContext> apnList = dcac.getApnListSync();
+ if (apnList.isEmpty()) {
+ cancelReconnectAlarm(dcac);
+ }
+ }
}
/**
- * @param APNContext to clean
- * @return true if ApnContext is not connected anymore.
- * false if ApnContext still holds a connection.
+ * Cancels the alarm associated with DCAC.
+ *
+ * @param DataConnectionAc on which the alarm should be stopped.
*/
- private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
- if (apnContext == null) return true;
+ private void cancelReconnectAlarm(DataConnectionAc dcac) {
+ if (dcac == null) return;
- // Clear the reconnect alarm, if set.
- if (apnContext.getReconnectIntent() != null) {
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- am.cancel(apnContext.getReconnectIntent());
- apnContext.setReconnectIntent(null);
- }
+ PendingIntent intent = dcac.getReconnectIntentSync();
- if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
- if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
- return true;
+ if (intent != null) {
+ AlarmManager am =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+ am.cancel(intent);
+ dcac.setReconnectIntentSync(null);
}
-
- if (apnContext.getState() == State.FAILED) {
- apnContext.setState(State.IDLE);
- return true;
- }
- return false;
}
/**
@@ -844,9 +880,16 @@
return result;
}
+ private boolean dataConnectionNotInUse(DataConnectionAc dcac) {
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getDataConnectionAc() == dcac) return false;
+ }
+ return true;
+ }
+
private GsmDataConnection findFreeDataConnection() {
for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
- if (dcac.isInactiveSync()) {
+ if (dcac.isInactiveSync() && dataConnectionNotInUse(dcac)) {
log("findFreeDataConnection: found free GsmDataConnection");
return (GsmDataConnection) dcac.dataConnection;
}
@@ -926,18 +969,27 @@
if (refCount == 0) {
configureRetry(dc, apnContext.getApnType());
}
- apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
- apnContext.setApnSetting(apn);
+ apnContext.setDataConnectionAc(dcac);
apnContext.setDataConnection(dc);
}
+ apnContext.setApnSetting(apn);
+ apnContext.setState(State.INITING);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ // If reconnect alarm is active on this DataConnection, wait for the alarm being
+ // fired so that we don't disruppt data retry pattern engaged.
+ if (apnContext.getDataConnectionAc().getReconnectIntentSync() != null) {
+ if (DBG) log("setupData: data reconnection pending");
+ apnContext.setState(State.FAILED);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ return true;
+ }
+
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = apnContext;
dc.bringUp(msg, apn);
- apnContext.setState(State.INITING);
- mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
if (DBG) log("setupData: initing!");
return true;
}
@@ -969,6 +1021,49 @@
}
/**
+ * @param cid Connection id provided from RIL.
+ * @return DataConnectionAc associated with specified cid.
+ */
+ private DataConnectionAc findDataConnectionAcByCid(int cid) {
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.getCidSync() == cid) {
+ return dcac;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param dcacs Collection of DataConnectionAc reported from RIL.
+ * @return List of ApnContext whihc is connected, but does not present in
+ * data connection list reported from RIL.
+ */
+ private List<ApnContext> findApnContextToClean(Collection<DataConnectionAc> dcacs) {
+ if (dcacs == null) return null;
+
+ ArrayList<ApnContext> list = new ArrayList<ApnContext>();
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getState() == State.CONNECTED) {
+ boolean found = false;
+ for (DataConnectionAc dcac : dcacs) {
+ if (dcac == apnContext.getDataConnectionAc()) {
+ // ApnContext holds the ref to dcac present in data call list.
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // ApnContext does not have dcan reorted in data call list.
+ if (DBG) log("onDataStateChanged(ar): Connected apn not found in the list (" +
+ apnContext.toString() + ")");
+ list.add(apnContext);
+ }
+ }
+ }
+ return list;
+ }
+
+ /**
* @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
* or RIL_UNSOL_DATA_CALL_LIST_CHANGED
*/
@@ -985,91 +1080,102 @@
if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
+ if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
- // Create a hash map to store the dataCallState of each call id
+ // Create a hash map to store the dataCallState of each DataConnectionAc
// TODO: Depends on how frequent the DATA_CALL_LIST got updated,
// may cache response to reduce comparison.
- HashMap<Integer, DataCallState> response;
- response = new HashMap<Integer, DataCallState>();
- if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
- for (DataCallState dc : dataCallStates) {
- response.put(dc.cid, dc);
- if (DBG) log("onDataStateChanged(ar): " + dc.cid + ": " + dc.toString());
+ HashMap<DataCallState, DataConnectionAc> response;
+ response = new HashMap<DataCallState, DataConnectionAc>();
+ for (DataCallState dataCallState : dataCallStates) {
+ DataConnectionAc dcac = findDataConnectionAcByCid(dataCallState.cid);
+
+ if (dcac != null) response.put(dataCallState, dcac);
}
- // For each connected apn, check if there is a matched active
- // data call state, which has the same link properties.
- if (DBG) log(" ApnContext size=" + mApnContexts.values().size());
- for (ApnContext apnContext : mApnContexts.values()) {
- if (DBG){
- log("onDataStateChanged(ar): " + apnContext.toString());
- if (apnContext.getDataConnection() != null) {
- log("onDataStateChanged(ar): " + apnContext.getDataConnection().toString());
+ // step1: Find a list of "connected" APN which does not have reference to
+ // calls listed in the Data Call List.
+ List<ApnContext> apnsToClear = findApnContextToClean(response.values());
+
+ // step2: Check status of each calls in Data Call List.
+ // Collect list of ApnContext associated with the data call if the link
+ // has to be cleared.
+ for (DataCallState newState : dataCallStates) {
+ DataConnectionAc dcac = response.get(newState);
+
+ // no associated DataConnection found. Ignore.
+ if (dcac == null) continue;
+
+ Collection<ApnContext> apns = dcac.getApnListSync();
+
+ // filter out ApnContext with "Connected" state.
+ ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
+ for (ApnContext apnContext : apns) {
+ if (apnContext.getState() == State.CONNECTED) {
+ connectedApns.add(apnContext);
}
}
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
- if (dcac == null) {
+
+ // No "Connected" ApnContext associated with this CID. Ignore.
+ if (connectedApns.isEmpty()) {
continue;
}
- int connectionId = dcac.getCidSync();
- if (apnContext.getState() == State.CONNECTED) {
- // The way things are supposed to work, the PDP list
- // should not contain the CID after it disconnects.
- // However, the way things really work, sometimes the PDP
- // context is still listed with active = false, which
- // makes it hard to distinguish an activating context from
- // an activated-and-then de-activated one.
- if (response.containsKey(connectionId)) {
- DataCallState newState = response.get(connectionId);
- if (DBG) log("onDataStateChanged(ar): Found ConnId=" + connectionId
+ if (DBG) log("onDataStateChanged(ar): Found ConnId=" + newState.cid
+ " newState=" + newState.toString());
- if (newState.active != 0) {
- boolean resetConnection;
- switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
- case NONE:
- if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
- resetConnection = false;
- break;
- case CHANGED:
- if (DBG) log("onDataStateChanged(ar): Found and changed, notify");
- mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
- apnContext.getApnType());
- // Temporary hack, at this time a transition from CDMA -> Global
- // fails so we'll hope for the best and not reset the connection.
- // @see bug/4455071
- if (SystemProperties.getBoolean("telephony.ignore-state-changes",
- true)) {
- log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
- resetConnection = false;
- } else {
- // Things changed so reset connection, when hack is removed
- // this is the normal path.
- log("onDataStateChanged(ar): changed so resetting connection");
- resetConnection = true;
- }
- break;
- case RESET:
- default:
- if (DBG) log("onDataStateChanged(ar): an error, reset connection");
- resetConnection = true;
- break;
- }
- if (resetConnection == false) continue;
+ if (newState.active != 0) {
+ boolean resetConnection;
+ switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
+ case NONE:
+ if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
+ resetConnection = false;
+ break;
+ case CHANGED:
+ for (ApnContext apnContext : connectedApns) {
+ if (DBG) log("onDataStateChanged(ar): Found and changed, notify (" +
+ apnContext.toString() + ")");
+ mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
+ apnContext.getApnType());
}
+ // Temporary hack, at this time a transition from CDMA -> Global
+ // fails so we'll hope for the best and not reset the connection.
+ // @see bug/4455071
+ if (SystemProperties.getBoolean("telephony.ignore-state-changes",
+ true)) {
+ log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
+ resetConnection = false;
+ } else {
+ // Things changed so reset connection, when hack is removed
+ // this is the normal path.
+ log("onDataStateChanged(ar): changed so resetting connection");
+ resetConnection = true;
+ }
+ break;
+ case RESET:
+ default:
+ if (DBG) log("onDataStateChanged(ar): an error, reset connection");
+ resetConnection = true;
+ break;
}
-
- if (DBG) log("onDataStateChanged(ar): reset connection.");
-
- // Add an event log when the network drops PDP
- int cid = getCellLocationId();
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
- TelephonyManager.getDefault().getNetworkType());
-
- cleanUpConnection(true, apnContext);
+ if (resetConnection == false) continue;
}
+
+ if (DBG) log("onDataStateChanged(ar): reset connection.");
+
+ apnsToClear.addAll(connectedApns);
}
+ // step3: Clear apn connection if applicable.
+ if (!apnsToClear.isEmpty()) {
+ // Add an event log when the network drops PDP
+ int cid = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
+ TelephonyManager.getDefault().getNetworkType());
+ }
+
+ for (ApnContext apnContext : apnsToClear) {
+ cleanUpConnection(true, apnContext);
+ }
if (DBG) log("onDataStateChanged(ar): X");
}
@@ -1332,7 +1438,8 @@
return retry;
}
- private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
+ private void reconnectAfterFail(FailCause lastFailCauseCode,
+ ApnContext apnContext, int retryOverride) {
if (apnContext == null) {
loge("reconnectAfterFail: apnContext == null, impossible");
return;
@@ -1357,9 +1464,14 @@
}
}
- int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+ // If retry needs to be backed off for specific case (determined by RIL/Modem)
+ // use the specified timer instead of pre-configured retry pattern.
+ int nextReconnectDelay = retryOverride;
+ if (nextReconnectDelay < 0) {
+ nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+ apnContext.getDataConnection().increaseRetryCount();
+ }
startAlarmForReconnect(nextReconnectDelay, apnContext);
- apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
if (DBG) {
@@ -1379,21 +1491,28 @@
+ (delay / 1000) + "s");
}
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+
+ if ((dcac == null) || (dcac.dataConnection == null)) {
+ // should not happen, but just in case.
+ loge("null dcac or dc.");
+ return;
+ }
+
AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- // TODO : Register the receiver only once maybe in baseclass.
- IntentFilter filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
- mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
-
- Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
+ Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
+ dcac.dataConnection.getDataConnectionId());
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
- apnContext.setReconnectIntent(PendingIntent.getBroadcast (
- mPhone.getContext(), 0, intent, 0));
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
+ dcac.dataConnection.getDataConnectionId());
+
+ PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
+ intent, 0);
+ dcac.setReconnectIntentSync(alarmIntent);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
+ SystemClock.elapsedRealtime() + delay, alarmIntent);
}
@@ -1412,13 +1531,16 @@
createAllApnList();
if (mRadioAvailable) {
if (DBG) log("onRecordsLoaded: notifying data availability");
- notifyDataAvailability(null);
+ notifyDataAvailability(Phone.REASON_SIM_LOADED);
}
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
@Override
protected void onSetDependencyMet(String apnType, boolean met) {
+ // don't allow users to tweak hipri to work around default dependency not met
+ if (Phone.APN_TYPE_HIPRI.equals(apnType)) return;
+
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext == null) {
loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
@@ -1426,6 +1548,11 @@
return;
}
applyNewState(apnContext, apnContext.isEnabled(), met);
+ if (Phone.APN_TYPE_DEFAULT.equals(apnType)) {
+ // tie actions on default to similar actions on HIPRI regarding dependencyMet
+ apnContext = mApnContexts.get(Phone.APN_TYPE_HIPRI);
+ if (apnContext != null) applyNewState(apnContext, apnContext.isEnabled(), met);
+ }
}
private void applyNewState(ApnContext apnContext, boolean enabled, boolean met) {
@@ -1511,11 +1638,17 @@
@Override
protected void onRoamingOff() {
if (DBG) log("onRoamingOff");
+ // Notify data availability so APN can be enabled.
+ notifyDataAvailability(Phone.REASON_ROAMING_OFF);
+
setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
}
@Override
protected void onRoamingOn() {
+ // Notify data availability so APN can be enabled.
+ notifyDataAvailability(Phone.REASON_ROAMING_ON);
+
if (getDataOnRoamingEnabled()) {
if (DBG) log("onRoamingOn: setup data on roaming");
setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
@@ -1664,7 +1797,13 @@
}
} else {
if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
- startDelayedRetry(cause, apnContext);
+ // check to see if retry should be overridden for this failure.
+ int retryOverride = -1;
+ if (ar.exception instanceof DataConnection.CallSetupException) {
+ retryOverride =
+ ((DataConnection.CallSetupException)ar.exception).getRetryOverride();
+ }
+ startDelayedRetry(cause, apnContext, retryOverride);
}
} else {
if (DBG) log("onDataSetupComplete: Try next APN");
@@ -1692,9 +1831,6 @@
}
apnContext.setState(State.IDLE);
- apnContext.setApnSetting(null);
- apnContext.setDataConnection(null);
- apnContext.setDataConnectionAc(null);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
@@ -1703,6 +1839,9 @@
if (!isConnected()) {
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
// Radio will be turned off. No need to retry data setup
+ apnContext.setApnSetting(null);
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
return;
}
}
@@ -1714,6 +1853,10 @@
// we're not tying up the RIL command channel.
// This also helps in any external dependency to turn off the context.
startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
+ } else {
+ apnContext.setApnSetting(null);
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
}
}
@@ -1839,6 +1982,11 @@
" status=" + status);
}
+ // install reconnect intent filter for this data connection.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_RECONNECT_ALARM + '.' + id);
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
if (DBG) log("createDataConnection() X id=" + id);
return conn;
}
@@ -1936,9 +2084,10 @@
return result.toString();
}
- private void startDelayedRetry(GsmDataConnection.FailCause cause, ApnContext apnContext) {
+ private void startDelayedRetry(GsmDataConnection.FailCause cause,
+ ApnContext apnContext, int retryOverride) {
notifyNoData(cause, apnContext);
- reconnectAfterFail(cause, apnContext);
+ reconnectAfterFail(cause, apnContext, retryOverride);
}
private void setPreferredApn(int pos) {
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index c4a6f53..6e9d0f9d 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -502,16 +502,17 @@
@SmallTest
public void testFormatNumberToE164() {
- assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "us"));
- assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "us"));
- assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "us"));
+ // Note: ISO 3166-1 only allows upper case country codes.
+ assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
+ assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
+ assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
}
@SmallTest
public void testFormatNumber() {
- assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "us"));
- assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "us"));
- assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "us"));
+ assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
+ assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "US"));
+ assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
}
diff --git a/tests/BiDiTests/AndroidManifest.xml b/tests/BiDiTests/AndroidManifest.xml
index 4a687f2..c60edd8 100644
--- a/tests/BiDiTests/AndroidManifest.xml
+++ b/tests/BiDiTests/AndroidManifest.xml
@@ -30,5 +30,6 @@
</activity>
</application>
-
+ <uses-sdk android:minSdkVersion="10"
+ android:targetSdkVersion="10"/>
</manifest>
diff --git a/tests/BiDiTests/res/drawable/end.png b/tests/BiDiTests/res/drawable/end.png
new file mode 100644
index 0000000..0c110be
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/end.png
Binary files differ
diff --git a/tests/BiDiTests/res/drawable/start.png b/tests/BiDiTests/res/drawable/start.png
new file mode 100644
index 0000000..783bf90
--- /dev/null
+++ b/tests/BiDiTests/res/drawable/start.png
Binary files differ
diff --git a/tests/BiDiTests/res/layout/textview_direction_ltr.xml b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
new file mode 100644
index 0000000..f7b7b8e
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_ltr.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_direction_ltr"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="ltr">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textDirection="ltr">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="inherit"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="firstStrong"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="anyRtl"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="ltr"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="rtl"
+ />
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="inherit"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="firstStrong"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="anyRtl"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="ltr"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="rtl"
+ />
+ </LinearLayout>
+
+ </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/textview_direction_rtl.xml b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
new file mode 100644
index 0000000..81c5411
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_direction_rtl.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_direction_rtl"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="rtl">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textDirection="rtl">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="inherit"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="firstStrong"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="anyRtl"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="ltr"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_text"
+ android:textDirection="rtl"
+ />
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="inherit"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="firstStrong"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="anyRtl"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="ltr"
+ />
+ <TextView android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:textDirection="rtl"
+ />
+ </LinearLayout>
+
+ </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/textview_locale.xml b/tests/BiDiTests/res/layout/textview_locale.xml
new file mode 100644
index 0000000..a2dcbf9
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_locale.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_locale"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="locale">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+
+ </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_ltr.xml b/tests/BiDiTests/res/layout/textview_ltr.xml
new file mode 100644
index 0000000..6e6b976
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_ltr.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_ltr"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="ltr">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+
+ </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_rtl.xml b/tests/BiDiTests/res/layout/textview_rtl.xml
new file mode 100644
index 0000000..117227d
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_rtl.xml
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/textview_rtl"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layoutDirection="rtl">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="start"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="end"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="left"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="right"
+ />
+
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_hebrew_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_latin_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+ <TextView android:id="@+id/textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="24dip"
+ android:text="@string/textview_multiline_text"
+ android:minWidth="200dip"
+ android:drawableLeft="@drawable/start"
+ android:drawableRight="@drawable/end"
+ android:paddingLeft="5dip"
+ android:paddingRight="15dip"
+ android:drawablePadding="3dip"
+ android:background="#884"
+ android:layout_marginLeft="5dip"
+ android:layout_marginRight="15dip"
+ android:gravity="center"
+ />
+
+ </LinearLayout>
+
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/view_group_margin_mixed.xml b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
new file mode 100644
index 0000000..5845b38
--- /dev/null
+++ b/tests/BiDiTests/res/layout/view_group_margin_mixed.xml
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/view_group_margin_mixed"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="#FFFFFFFF">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="ltr">
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF0000FF">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="0dip"
+ android:layout_marginRight="0dip"
+ android:layout_marginTop="0dip"
+ android:layout_marginBottom="0dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF000000">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="10dip"
+ android:layout_marginStart="5dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginEnd="5dip"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="rtl">
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF0000FF">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="0dip"
+ android:layout_marginRight="0dip"
+ android:layout_marginTop="0dip"
+ android:layout_marginBottom="0dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF000000">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="10dip"
+ android:layout_marginStart="5dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginEnd="5dip"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="inherit">
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF0000FF">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="0dip"
+ android:layout_marginRight="0dip"
+ android:layout_marginTop="0dip"
+ android:layout_marginBottom="0dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF000000">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="10dip"
+ android:layout_marginStart="5dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginEnd="5dip"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layoutDirection="locale">
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF0000FF">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="0dip"
+ android:layout_marginRight="0dip"
+ android:layout_marginTop="0dip"
+ android:layout_marginBottom="0dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ <LinearLayout android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="#FF000000">
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_marginLeft="10dip"
+ android:layout_marginStart="5dip"
+ android:layout_marginRight="20dip"
+ android:layout_marginEnd="5dip"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="#FFFF0000">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/view_padding_mixed.xml b/tests/BiDiTests/res/layout/view_padding_mixed.xml
new file mode 100644
index 0000000..c916ffb
--- /dev/null
+++ b/tests/BiDiTests/res/layout/view_padding_mixed.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/view_padding_mixed"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <FrameLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#FFFFFFFF">
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="top|left"
+ android:background="#FF888888"
+ android:paddingTop="20dip"
+ android:paddingLeft="40dip"
+ android:paddingStart="5dip"
+ android:paddingBottom="30dip"
+ android:paddingRight="50dip"
+ android:layoutDirection="ltr">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="top|center_horizontal"
+ android:background="#FF888888"
+ android:paddingTop="20dip"
+ android:paddingLeft="40dip"
+ android:paddingEnd="5dip"
+ android:paddingBottom="30dip"
+ android:paddingRight="50dip"
+ android:layoutDirection="ltr">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="top|right"
+ android:background="@*android:drawable/dialog_full_holo_dark"
+ android:layoutDirection="ltr">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FFFFFFFF">
+ </FrameLayout>
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="bottom|left"
+ android:background="#FF888888"
+ android:paddingTop="20dip"
+ android:paddingLeft="40dip"
+ android:paddingStart="5dip"
+ android:paddingBottom="30dip"
+ android:paddingRight="50dip"
+ android:layoutDirection="rtl">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="bottom|center_horizontal"
+ android:background="#FF888888"
+ android:paddingTop="20dip"
+ android:paddingLeft="40dip"
+ android:paddingEnd="5dip"
+ android:paddingBottom="30dip"
+ android:paddingRight="50dip"
+ android:layoutDirection="rtl">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FF00FF00">
+ </FrameLayout>
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="300dp"
+ android:layout_height="300dp"
+ android:layout_gravity="bottom|right"
+ android:background="@*android:drawable/menu_background_fill_parent_width"
+ android:layoutDirection="ltr">
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="top|left"
+ android:background="#FF0000FF">
+ </FrameLayout>
+
+ <FrameLayout
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:layout_gravity="bottom|right"
+ android:background="#FFFFFFFF">
+ </FrameLayout>
+ </FrameLayout>
+
+ </FrameLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/menu/main_menu.xml b/tests/BiDiTests/res/menu/main_menu.xml
new file mode 100644
index 0000000..a7fe28a
--- /dev/null
+++ b/tests/BiDiTests/res/menu/main_menu.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_menu">
+
+ <item android:id="@+id/menu_add"
+ android:icon="@android:drawable/ic_menu_add"
+ android:title="@string/menu_add" />
+
+ <item android:id="@+id/menu_delete"
+ android:icon="@android:drawable/ic_menu_delete"
+ android:title="@string/menu_delete" />
+
+</menu>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index d067e7d..c0bbe94 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -36,4 +36,10 @@
<string name="bold_italic_text">Bold Italic String</string>
<string name="mixed_text_1">he said in Arabic: لا. Wow this is cool</string>
<string name="hebrew_text">םמ</string>
-</resources>
\ No newline at end of file
+ <string name="menu_add">Add</string>
+ <string name="menu_delete">Delete</string>
+ <string name="textview_hebrew_text">םמab?!</string>
+ <string name="textview_latin_text">abםמ?!</string>
+ <string name="textview_multiline_text">םמ?!\nab?!</string>
+</resources>
+
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index 0bed7ce..c033879 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -25,6 +25,8 @@
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
@@ -98,29 +100,47 @@
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
addItem(result, "Basic", BiDiTestBasic.class, R.id.basic);
+
addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
-
+
addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
addItem(result, "Linear LOC", BiDiTestLinearLayoutLocale.class, R.id.linear_layout_locale);
-
+
addItem(result, "Frame LTR", BiDiTestFrameLayoutLtr.class, R.id.frame_layout_ltr);
addItem(result, "Frame RTL", BiDiTestFrameLayoutRtl.class, R.id.frame_layout_rtl);
addItem(result, "Frame LOC", BiDiTestFrameLayoutLocale.class, R.id.frame_layout_locale);
-
+
addItem(result, "Relative LTR", BiDiTestRelativeLayoutLtr.class, R.id.relative_layout_ltr);
addItem(result, "Relative RTL", BiDiTestRelativeLayoutRtl.class, R.id.relative_layout_rtl);
-
+
addItem(result, "Relative2 LTR", BiDiTestRelativeLayout2Ltr.class, R.id.relative_layout_2_ltr);
addItem(result, "Relative2 RTL", BiDiTestRelativeLayout2Rtl.class, R.id.relative_layout_2_rtl);
addItem(result, "Relative2 LOC", BiDiTestRelativeLayout2Locale.class, R.id.relative_layout_2_locale);
-
+
addItem(result, "Table LTR", BiDiTestTableLayoutLtr.class, R.id.table_layout_ltr);
addItem(result, "Table RTL", BiDiTestTableLayoutRtl.class, R.id.table_layout_rtl);
addItem(result, "Table LOC", BiDiTestTableLayoutLocale.class, R.id.table_layout_locale);
- addItem(result, "ViewPadding", BiDiTestViewPadding.class, R.id.view_padding);
+ addItem(result, "Padding", BiDiTestViewPadding.class, R.id.view_padding);
+ addItem(result, "Padding MIXED", BiDiTestViewPaddingMixed.class, R.id.view_padding_mixed);
+
+ addItem(result, "Margin MIXED", BiDiTestViewGroupMarginMixed.class, R.id.view_group_margin_mixed);
+
+ addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
+ addItem(result, "TextView RTL", BiDiTestTextViewRtl.class, R.id.textview_rtl);
+ addItem(result, "TextView LOC", BiDiTestTextViewLocale.class, R.id.textview_locale);
+
+ addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
+ addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
return result;
}
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main_menu, menu);
+ return true;
+ }
}
\ No newline at end of file
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
new file mode 100644
index 0000000..882ed1f
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionLtr.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionLtr extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.textview_direction_ltr, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
new file mode 100644
index 0000000..e63ee35
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDirectionRtl.java
@@ -0,0 +1,31 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewDirectionRtl extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.textview_direction_rtl, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java
new file mode 100644
index 0000000..6c64755
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLocale.java
@@ -0,0 +1,32 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewLocale extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.textview_locale, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java
new file mode 100644
index 0000000..b168411
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewLtr.java
@@ -0,0 +1,32 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewLtr extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.textview_ltr, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java
new file mode 100644
index 0000000..6f36ce6
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewRtl.java
@@ -0,0 +1,32 @@
+/*
+ * 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.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewRtl extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.textview_rtl, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
new file mode 100644
index 0000000..ce8c380
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewGroupMarginMixed.java
@@ -0,0 +1,17 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestViewGroupMarginMixed extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.view_group_margin_mixed, container, false);
+ }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewPaddingMixed.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewPaddingMixed.java
new file mode 100644
index 0000000..7ca2707
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewPaddingMixed.java
@@ -0,0 +1,17 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestViewPaddingMixed extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.view_padding_mixed, container, false);
+ }
+}
diff --git a/tests/CoreTests/MODULE_LICENSE_APACHE2 b/tests/CoreTests/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/tests/CoreTests/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 4294254..d373d8d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -85,6 +85,12 @@
// This first block of tests are for features for which Android
// should pass all tests. They are skipped only temporarily.
// TODO: Fix these failing tests and remove them from this list.
+ ignoreResultList.add("fast/dom/HTMLKeygenElement/keygen.html"); // Missing layoutTestController.shadowRoot()
+ ignoreResultList.add("fast/dom/Geolocation/window-close-crash.html"); // Missing layoutTestContoller.setCloseRemainingWindowsWhenComplete()
+ ignoreResultList.add("fast/dom/Geolocation/page-reload-cancel-permission-requests.html"); // Missing layoutTestController.numberOfPendingGeolocationPermissionRequests()
+ ignoreResultList.add("fast/dom/HTMLLinkElement/link-and-subresource-test.html"); // Missing layoutTestController.dumpResourceResponseMIMETypes()
+ ignoreResultList.add("fast/dom/HTMLLinkElement/prefetch.html"); // Missing layoutTestController.dumpResourceResponseMIMETypes()
+ ignoreResultList.add("fast/dom/HTMLLinkElement/subresource.html"); // Missing layoutTestController.dumpResourceResponseMIMETypes()
ignoreResultList.add("fast/encoding/char-decoding.html"); // fails in Java HTTP stack, see http://b/issue?id=3047156
ignoreResultList.add("fast/encoding/hanarei-blog32-fc2-com.html"); // fails in Java HTTP stack, see http://b/issue?id=3046986
ignoreResultList.add("fast/encoding/mailto-always-utf-8.html"); // Requires waitForPolicyDelegate(), see http://b/issue?id=3043468
@@ -100,9 +106,16 @@
ignoreResultList.add("storage/open-database-creation-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
ignoreResultList.add("storage/statement-error-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
ignoreResultList.add("storage/statement-success-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
+ ignoreResultList.add("storage/storageinfo-query-usage.html"); // Need window.webkitStorageInfo
ignoreResultList.add("storage/transaction-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
ignoreResultList.add("storage/transaction-error-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
ignoreResultList.add("storage/transaction-success-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
+ ignoreResultList.add("storage/domstorage/localstorage/storagetracker/storage-tracker-1-prepare.html"); // Missing layoutTestController.originsWithLocalStorage()
+ ignoreResultList.add("storage/domstorage/localstorage/storagetracker/storage-tracker-2-create.html"); // Missing layoutTestController.originsWithLocalStorage()
+ ignoreResultList.add("storage/domstorage/localstorage/storagetracker/storage-tracker-3-delete-all.html"); // Missing layoutTestController.originsWithLocalStorage()
+ ignoreResultList.add("storage/domstorage/localstorage/storagetracker/storage-tracker-4-create.html"); // Missing layoutTestController.originsWithLocalStorage()
+ ignoreResultList.add("storage/domstorage/localstorage/storagetracker/storage-tracker-5-delete-one.html"); // Missing layoutTestController.originsWithLocalStorage()
+
// Expected failures due to unsupported features or tests unsuitable for Android.
ignoreResultList.add("fast/encoding/char-decoding-mac.html"); // Mac-specific encodings (also marked Won't Fix in Chromium, bug 7388)
@@ -119,6 +132,7 @@
ignoreResultList.add("storage/domstorage/localstorage/private-browsing-affects-storage.html"); // private browsing not supported
ignoreResultList.add("storage/domstorage/sessionstorage/private-browsing-affects-storage.html"); // private browsing not supported
ignoreResultList.add("storage/indexeddb"); // indexeddb not supported
+ ignoreResultList.add("storage/private-browsing-noread-nowrite.html"); // private browsing not supported
ignoreResultList.add("storage/private-browsing-readonly.html"); // private browsing not supported
ignoreResultList.add("websocket/tests/workers"); // workers not supported
ignoreResultList.add("dom/xhtml/level2/html/htmldocument04.xhtml"); // /mnt/sdcard on SR uses lowercase filesystem, this test checks filename and is case senstive.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index fa82070..f8c32dd 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -207,6 +207,11 @@
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, progress);
Log.v(LOGTAG, " Loading " + mTestUrl);
+
+ if (mTestUrl.contains("/dumpAsText/")) {
+ dumpAsText(false);
+ }
+
mWebView.loadUrl(mTestUrl);
if (mTimeoutInMillis > 0) {
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index 5cdacf7..ba911c2 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -21,7 +21,7 @@
android:layout_height="match_parent"
android:useDefaultMargins="true"
- android:marginsIncludedInAlignment="false"
+ android:alignmentMode="alignBounds"
android:columnCount="4"
>
diff --git a/tests/GridLayoutTest/res/layout/grid7.xml b/tests/GridLayoutTest/res/layout/grid7.xml
index b97a00b..b9e58d7 100644
--- a/tests/GridLayoutTest/res/layout/grid7.xml
+++ b/tests/GridLayoutTest/res/layout/grid7.xml
@@ -15,56 +15,26 @@
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
-
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:orientation="horizontal"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="10dip" >
+ android:layout_height="match_parent">
+ android:columnCount="2"
+ <Space
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_width="109dip"
+ android:layout_height="108dip"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="5dip"
- android:text="flabe" />
+ <Button
+ android:text="Button 1"
+ android:layout_row="0"
+ android:layout_column="1"
+ />
- <Button android:id="@+id/initialActivity"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="bax" />
- </LinearLayout>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="5dip"
- android:text="bar" />
-
- <EditText android:id="@+id/numberOfEvents"
- android:layout_marginLeft="2dip"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@android:drawable/editbox_background"
- android:numeric="integer"
- android:scrollHorizontally="true"
- android:maxLines="1" />
- </LinearLayout>
-
- <Button android:id="@+id/start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="10dip"
- android:text="Foo" />
+ <Button
+ android:text="Button 2"
+ android:layout_row="1"
+ android:layout_column="1"
+ />
</GridLayout>
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index 32365d7..e010a00 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -36,7 +36,7 @@
public static View create(Context context) {
GridLayout vg = new GridLayout(context);
vg.setUseDefaultMargins(true);
- vg.setMarginsIncludedInAlignment(false);
+ vg.setAlignmentMode(ALIGN_BOUNDS);
Group row1 = new Group(1, CENTER);
Group row2 = new Group(2, CENTER);
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 3e7ca08..8734143 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,42 @@
android:hardwareAccelerated="true">
<activity
+ android:name="TimeDialogActivity"
+ android:label="_TimeDialog">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="OpaqueActivity"
+ android:label="_Opaque">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="GetBitmapActivity"
+ android:label="_GetBitmap">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="SmallCircleActivity"
+ android:label="_SmallCircle">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ClearActivity"
android:label="_Clear">
<intent-filter>
@@ -467,8 +503,7 @@
<activity
android:name="Animated3dActivity"
- android:label="_Animated 3d"
- android:theme="@android:style/Theme.Translucent.NoTitleBar">
+ android:label="_Animated 3d">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 9bb5ba8..e1ca756 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -19,13 +19,17 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
+import android.opengl.GLUtils;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.TextureView;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.FrameLayout;
import javax.microedition.khronos.egl.EGL10;
@@ -36,6 +40,12 @@
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import static android.opengl.GLES20.*;
+
@SuppressWarnings({"UnusedDeclaration"})
public class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
private RenderThread mRenderThread;
@@ -48,12 +58,14 @@
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
- setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+ setContentView(mTextureView, new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
+ Gravity.CENTER));
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- mRenderThread = new RenderThread(surface);
+ mRenderThread = new RenderThread(getResources(), surface);
mRenderThread.start();
mTextureView.setCameraDistance(5000);
@@ -85,17 +97,20 @@
}
}
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ }
+
private static class RenderThread extends Thread {
private static final String LOG_TAG = "GLTextureView";
static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- static final int EGL_SURFACE_TYPE = 0x3033;
- static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
static final int EGL_OPENGL_ES2_BIT = 4;
private volatile boolean mFinished;
- private SurfaceTexture mSurface;
+ private final Resources mResources;
+ private final SurfaceTexture mSurface;
private EGL10 mEgl;
private EGLDisplay mEglDisplay;
@@ -104,26 +119,96 @@
private EGLSurface mEglSurface;
private GL mGL;
- RenderThread(SurfaceTexture surface) {
+ RenderThread(Resources resources, SurfaceTexture surface) {
+ mResources = resources;
mSurface = surface;
}
+ private static final String sSimpleVS =
+ "attribute vec4 position;\n" +
+ "attribute vec2 texCoords;\n" +
+ "varying vec2 outTexCoords;\n" +
+ "\nvoid main(void) {\n" +
+ " outTexCoords = texCoords;\n" +
+ " gl_Position = position;\n" +
+ "}\n\n";
+ private static final String sSimpleFS =
+ "precision mediump float;\n\n" +
+ "varying vec2 outTexCoords;\n" +
+ "uniform sampler2D texture;\n" +
+ "\nvoid main(void) {\n" +
+ " gl_FragColor = texture2D(texture, outTexCoords);\n" +
+ "}\n\n";
+
+ private static final int FLOAT_SIZE_BYTES = 4;
+ private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+ private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+ private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+ private final float[] mTriangleVerticesData = {
+ // X, Y, Z, U, V
+ -1.0f, -1.0f, 0, 0.f, 0.f,
+ 1.0f, -1.0f, 0, 1.f, 0.f,
+ -1.0f, 1.0f, 0, 0.f, 1.f,
+ 1.0f, 1.0f, 0, 1.f, 1.f,
+ };
+
@Override
public void run() {
initGL();
+
+ FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
+ * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ triangleVertices.put(mTriangleVerticesData).position(0);
- float red = 1.0f;
+ int texture = loadTexture(R.drawable.large_photo);
+ int program = buildProgram(sSimpleVS, sSimpleFS);
+
+ int attribPosition = glGetAttribLocation(program, "position");
+ checkGlError();
+
+ int attribTexCoords = glGetAttribLocation(program, "texCoords");
+ checkGlError();
+
+ int uniformTexture = glGetUniformLocation(program, "texture");
+ checkGlError();
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ checkGlError();
+
+ glUseProgram(program);
+ checkGlError();
+
+ glEnableVertexAttribArray(attribPosition);
+ checkGlError();
+
+ glEnableVertexAttribArray(attribTexCoords);
+ checkGlError();
+
+ glUniform1i(texture, 0);
+ checkGlError();
+
while (!mFinished) {
checkCurrent();
Log.d(LOG_TAG, "Rendering frame");
- GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
checkGlError();
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT);
checkGlError();
+ // drawQuad
+ triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+ glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+ triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+ glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
throw new RuntimeException("Cannot swap buffers");
}
@@ -134,14 +219,90 @@
} catch (InterruptedException e) {
// Ignore
}
-
- red += 0.021f;
- if (red > 1.0f) red = 0.0f;
}
finishGL();
}
+ private int loadTexture(int resource) {
+ int[] textures = new int[1];
+
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1, textures, 0);
+ checkGlError();
+
+ int texture = textures[0];
+ glBindTexture(GL_TEXTURE_2D, texture);
+ checkGlError();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
+
+ GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
+ checkGlError();
+
+ bitmap.recycle();
+
+ return texture;
+ }
+
+ private int buildProgram(String vertex, String fragment) {
+ int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+ if (vertexShader == 0) return 0;
+
+ int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+ if (fragmentShader == 0) return 0;
+
+ int program = glCreateProgram();
+ glAttachShader(program, vertexShader);
+ checkGlError();
+
+ glAttachShader(program, fragmentShader);
+ checkGlError();
+
+ glLinkProgram(program);
+ checkGlError();
+
+ int[] status = new int[1];
+ glGetProgramiv(program, GL_LINK_STATUS, status, 0);
+ if (status[0] != GL_TRUE) {
+ String error = glGetProgramInfoLog(program);
+ Log.d(LOG_TAG, "Error while linking program:\n" + error);
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ glDeleteProgram(program);
+ return 0;
+ }
+
+ return program;
+ }
+
+ private int buildShader(String source, int type) {
+ int shader = glCreateShader(type);
+
+ glShaderSource(shader, source);
+ checkGlError();
+
+ glCompileShader(shader);
+ checkGlError();
+
+ int[] status = new int[1];
+ glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
+ if (status[0] != GL_TRUE) {
+ String error = glGetShaderInfoLog(shader);
+ Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
+ glDeleteShader(shader);
+ return 0;
+ }
+
+ return shader;
+ }
+
private void checkEglError() {
int error = mEgl.eglGetError();
if (error != EGL10.EGL_SUCCESS) {
@@ -150,8 +311,8 @@
}
private void checkGlError() {
- int error = GLES20.glGetError();
- if (error != GLES20.GL_NO_ERROR) {
+ int error = glGetError();
+ if (error != GL_NO_ERROR) {
Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
}
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java
new file mode 100644
index 0000000..f420fa0
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapActivity.java
@@ -0,0 +1,108 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.Gravity;
+import android.view.TextureView;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class GetBitmapActivity extends Activity implements TextureView.SurfaceTextureListener {
+ private Camera mCamera;
+ private TextureView mTextureView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout content = new FrameLayout(this);
+
+ mTextureView = new TextureView(this);
+ mTextureView.setSurfaceTextureListener(this);
+
+ Button button = new Button(this);
+ button.setText("Copy bitmap to /sdcard/textureview.png");
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Bitmap b = mTextureView.getBitmap();
+ try {
+ FileOutputStream out = new FileOutputStream(
+ Environment.getExternalStorageDirectory() + "/textureview.png");
+ try {
+ b.compress(Bitmap.CompressFormat.PNG, 100, out);
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Ignore
+ }
+ }
+ });
+
+ content.addView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+ content.addView(button, new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
+ setContentView(content);
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ mCamera = Camera.open();
+
+ try {
+ mCamera.setPreviewTexture(surface);
+ } catch (IOException t) {
+ android.util.Log.e("TextureView", "Cannot set preview texture target!", t);
+ }
+
+ mCamera.startPreview();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ // Ignored, the Camera does all the work for us
+ }
+
+ @Override
+ public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ mCamera.stopPreview();
+ mCamera.release();
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ // Ignored
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java
new file mode 100644
index 0000000..af45f29
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/OpaqueActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class OpaqueActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final OpaqueView view = new OpaqueView(this);
+ setContentView(view, new FrameLayout.LayoutParams(100, 100, Gravity.CENTER));
+ }
+
+ public static class OpaqueView extends View {
+ public OpaqueView(Context c) {
+ super(c);
+ setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ invalidate();
+ Log.d("OpaqueView", "Invalidate");
+ }
+ });
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawColor(0xffff0000, PorterDuff.Mode.SRC);
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
new file mode 100644
index 0000000..8c02539
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.LinearLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SmallCircleActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ View view = new PathView(this);
+ layout.addView(view, new LinearLayout.LayoutParams(PathView.SIZE, PathView.SIZE));
+ view = new PathView(this);
+ view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ layout.addView(view, new LinearLayout.LayoutParams(PathView.SIZE, PathView.SIZE));
+
+ setContentView(layout);
+ }
+
+ static class PathView extends View {
+ private static final int SIZE = 37;
+ private final Paint mPaint;
+ private final Path mPath;
+
+ PathView(Context c) {
+ super(c);
+
+ mPath = new Path();
+ mPath.addCircle(SIZE * 0.5f, SIZE * 0.5f, SIZE * 0.275f, Path.Direction.CW);
+ mPath.addCircle(SIZE * 0.5f, SIZE * 0.5f, SIZE * 0.225f, Path.Direction.CCW);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(0xffffffff);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.drawPath(mPath, mPaint);
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index fa2e39a..c857ded 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -17,8 +17,6 @@
package com.android.test.hwui;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
@@ -55,7 +53,7 @@
@Override
public void onClick(View v) {
if (mAdded) {
- mAnimatorSet.cancel();
+ if (mAnimatorSet != null) mAnimatorSet.cancel();
mContent.removeView(mTextureView);
} else {
mContent.addView(mTextureView);
@@ -85,25 +83,19 @@
mTextureView.setCameraDistance(5000);
- ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
- rotationY.setRepeatMode(ObjectAnimator.REVERSE);
- rotationY.setRepeatCount(ObjectAnimator.INFINITE);
- rotationY.setDuration(4000);
- rotationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- ((View) mTextureView.getParent()).invalidate();
- }
- });
+// ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
+// rotationY.setRepeatMode(ObjectAnimator.REVERSE);
+// rotationY.setRepeatCount(ObjectAnimator.INFINITE);
+// rotationY.setDuration(4000);
- ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
- alpha.setRepeatMode(ObjectAnimator.REVERSE);
- alpha.setRepeatCount(ObjectAnimator.INFINITE);
- alpha.setDuration(4000);
+// ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
+// alpha.setRepeatMode(ObjectAnimator.REVERSE);
+// alpha.setRepeatCount(ObjectAnimator.INFINITE);
+// alpha.setDuration(4000);
- mAnimatorSet = new AnimatorSet();
- mAnimatorSet.play(alpha).with(rotationY);
- mAnimatorSet.start();
+// mAnimatorSet = new AnimatorSet();
+// mAnimatorSet.play(alpha).with(rotationY);
+// mAnimatorSet.start();
}
@Override
@@ -116,4 +108,9 @@
mCamera.stopPreview();
mCamera.release();
}
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ // Ignored
+ }
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
new file mode 100644
index 0000000..9e3e950
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TimeDialogActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.app.TimePickerDialog;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TimeDialogActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout layout = new FrameLayout(this);
+ Button b = new Button(this);
+ b.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
+ b.setText("Show dialog");
+ b.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ new TimePickerDialog(TimeDialogActivity.this, null, 12, 12, true).show();
+ }
+ });
+ layout.addView(b);
+
+ setContentView(layout);
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index 3f57799..c706286 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -100,6 +100,7 @@
private ProgramVertex mProgVertex;
private ProgramVertexFixedFunction.Constants mPVA;
+ private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
// Custom shaders
private ProgramVertex mProgVertexCustom;
@@ -388,6 +389,7 @@
i.Proj = projNorm;
i.MVP = projNorm;
mPvStarAlloc.set(i, 0, true);
+ mPvProjectionAlloc.setProjection(projNorm);
}
private void initProgramVertex() {
@@ -405,8 +407,14 @@
// For galaxy live wallpaper
mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
mScript.bind_vpConstants(mPvStarAlloc);
+ mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
updateProjectionMatrices();
+ pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertex pvbp = pvb.create();
+ ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
+ mScript.set_gPVBkProj(pvbp);
+
ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
String t = "varying vec4 varColor;\n" +
"varying vec2 varTex0;\n" +
@@ -648,10 +656,10 @@
prepareTestData();
initSamplers();
- initProgramStore();
- initProgramFragment();
initMesh();
initProgramVertex();
+ initProgramStore();
+ initProgramFragment();
initFonts();
loadImages();
initProgramRaster();
@@ -674,7 +682,6 @@
Allocation.USAGE_GRAPHICS_RENDER_TARGET);
mScript.set_gRenderBufferDepth(offscreen);
-
mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
for (int i = 0; i < 100; i++) {
ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index 6d80b0e..bb81862 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -393,19 +393,28 @@
rsgBindProgramStore(gProgStoreBlendAlpha);
rsgBindProgramFragment(gProgFragmentTexture);
rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+ rsgDrawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
+ gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
+ gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
- float size = 50.0;
+ float wSize = gRenderSurfaceW/(float)meshCount;
+ float hSize = gRenderSurfaceH/(float)meshCount;
rs_matrix4x4 matrix;
- rsMatrixLoadScale(&matrix, size, size, 1.0);
+ rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
float yPos = 0;
+ float yPad = hSize / 2;
+ float xPad = wSize / 2;
for (int y = 0; y < meshCount; y++) {
- yPos = (y + 1) * 50;
+ yPos = y * hSize + yPad;
float xPos = 0;
for (int x = 0; x < meshCount; x++) {
- xPos = (x + 1) * 50;
+ xPos = x * wSize + xPad;
rs_matrix4x4 transMatrix;
rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
rsMatrixMultiply(&transMatrix, &matrix);
@@ -529,11 +538,12 @@
}
// Display images and text with live wallpaper in the background
-static void dispalyLiveWallPaper(int wResolution, int hResolution) {
+static void displayLiveWallPaper(int wResolution, int hResolution) {
bindProgramVertexOrtho();
drawGalaxy();
+ rsgBindProgramVertex(gProgVertex);
rsgBindProgramStore(gProgStoreBlendAlpha);
rsgBindProgramFragment(gProgFragmentTexture);
rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
@@ -958,7 +968,7 @@
displayListView();
break;
case 30:
- dispalyLiveWallPaper(7, 5);
+ displayLiveWallPaper(7, 5);
break;
}
}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
index 89fc34b..d1b23fa 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTest.java
@@ -39,7 +39,7 @@
public class RSTest extends Activity {
//EventListener mListener = new EventListener();
- private static final String LOG_TAG = "libRS_jni";
+ private static final String LOG_TAG = "RSTest";
private static final boolean DEBUG = false;
private static final boolean LOG_ENABLED = false;
@@ -73,6 +73,14 @@
mView.pause();
}
+ @Override
+ protected void onStop() {
+ // Actually kill the app if we are stopping. We don't want to
+ // continue/resume this test ever. It should always start fresh.
+ finish();
+ super.onStop();
+ }
+
static void log(String message) {
if (LOG_ENABLED) {
Log.v(LOG_TAG, message);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index 541bf22..e77998e 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2008-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.
@@ -65,6 +65,7 @@
unitTests = new ArrayList<UnitTest>();
unitTests.add(new UT_primitives(this, mRes, mCtx));
+ unitTests.add(new UT_vector(this, mRes, mCtx));
unitTests.add(new UT_rsdebug(this, mRes, mCtx));
unitTests.add(new UT_rstime(this, mRes, mCtx));
unitTests.add(new UT_rstypes(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
new file mode 100644
index 0000000..748701d
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
@@ -0,0 +1,318 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_vector extends UnitTest {
+ private Resources mRes;
+
+ protected UT_vector(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Vector", ctx);
+ mRes = res;
+ }
+
+ private boolean initializeGlobals(ScriptC_vector s) {
+ Float2 F2 = s.get_f2();
+ if (F2.x != 1.0f || F2.y != 2.0f) {
+ return false;
+ }
+ F2.x = 2.99f;
+ F2.y = 3.99f;
+ s.set_f2(F2);
+
+ Float3 F3 = s.get_f3();
+ if (F3.x != 1.0f || F3.y != 2.0f || F3.z != 3.0f) {
+ return false;
+ }
+ F3.x = 2.99f;
+ F3.y = 3.99f;
+ F3.z = 4.99f;
+ s.set_f3(F3);
+
+ Float4 F4 = s.get_f4();
+ if (F4.x != 1.0f || F4.y != 2.0f || F4.z != 3.0f || F4.w != 4.0f) {
+ return false;
+ }
+ F4.x = 2.99f;
+ F4.y = 3.99f;
+ F4.z = 4.99f;
+ F4.w = 5.99f;
+ s.set_f4(F4);
+
+ Double2 D2 = s.get_d2();
+ if (D2.x != 1.0 || D2.y != 2.0) {
+ return false;
+ }
+ D2.x = 2.99;
+ D2.y = 3.99;
+ s.set_d2(D2);
+
+ Double3 D3 = s.get_d3();
+ if (D3.x != 1.0 || D3.y != 2.0 || D3.z != 3.0) {
+ return false;
+ }
+ D3.x = 2.99;
+ D3.y = 3.99;
+ D3.z = 4.99;
+ s.set_d3(D3);
+
+ Double4 D4 = s.get_d4();
+ if (D4.x != 1.0 || D4.y != 2.0 || D4.z != 3.0 || D4.w != 4.0) {
+ return false;
+ }
+ D4.x = 2.99;
+ D4.y = 3.99;
+ D4.z = 4.99;
+ D4.w = 5.99;
+ s.set_d4(D4);
+
+ Byte2 B2 = s.get_i8_2();
+ if (B2.x != 1 || B2.y != 2) {
+ return false;
+ }
+ B2.x = 2;
+ B2.y = 3;
+ s.set_i8_2(B2);
+
+ Byte3 B3 = s.get_i8_3();
+ if (B3.x != 1 || B3.y != 2 || B3.z != 3) {
+ return false;
+ }
+ B3.x = 2;
+ B3.y = 3;
+ B3.z = 4;
+ s.set_i8_3(B3);
+
+ Byte4 B4 = s.get_i8_4();
+ if (B4.x != 1 || B4.y != 2 || B4.z != 3 || B4.w != 4) {
+ return false;
+ }
+ B4.x = 2;
+ B4.y = 3;
+ B4.z = 4;
+ B4.w = 5;
+ s.set_i8_4(B4);
+
+ Short2 S2 = s.get_u8_2();
+ if (S2.x != 1 || S2.y != 2) {
+ return false;
+ }
+ S2.x = 2;
+ S2.y = 3;
+ s.set_u8_2(S2);
+
+ Short3 S3 = s.get_u8_3();
+ if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+ return false;
+ }
+ S3.x = 2;
+ S3.y = 3;
+ S3.z = 4;
+ s.set_u8_3(S3);
+
+ Short4 S4 = s.get_u8_4();
+ if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+ return false;
+ }
+ S4.x = 2;
+ S4.y = 3;
+ S4.z = 4;
+ S4.w = 5;
+ s.set_u8_4(S4);
+
+ S2 = s.get_i16_2();
+ if (S2.x != 1 || S2.y != 2) {
+ return false;
+ }
+ S2.x = 2;
+ S2.y = 3;
+ s.set_i16_2(S2);
+
+ S3 = s.get_i16_3();
+ if (S3.x != 1 || S3.y != 2 || S3.z != 3) {
+ return false;
+ }
+ S3.x = 2;
+ S3.y = 3;
+ S3.z = 4;
+ s.set_i16_3(S3);
+
+ S4 = s.get_i16_4();
+ if (S4.x != 1 || S4.y != 2 || S4.z != 3 || S4.w != 4) {
+ return false;
+ }
+ S4.x = 2;
+ S4.y = 3;
+ S4.z = 4;
+ S4.w = 5;
+ s.set_i16_4(S4);
+
+ Int2 I2 = s.get_u16_2();
+ if (I2.x != 1 || I2.y != 2) {
+ return false;
+ }
+ I2.x = 2;
+ I2.y = 3;
+ s.set_u16_2(I2);
+
+ Int3 I3 = s.get_u16_3();
+ if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+ return false;
+ }
+ I3.x = 2;
+ I3.y = 3;
+ I3.z = 4;
+ s.set_u16_3(I3);
+
+ Int4 I4 = s.get_u16_4();
+ if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+ return false;
+ }
+ I4.x = 2;
+ I4.y = 3;
+ I4.z = 4;
+ I4.w = 5;
+ s.set_u16_4(I4);
+
+ I2 = s.get_i32_2();
+ if (I2.x != 1 || I2.y != 2) {
+ return false;
+ }
+ I2.x = 2;
+ I2.y = 3;
+ s.set_i32_2(I2);
+
+ I3 = s.get_i32_3();
+ if (I3.x != 1 || I3.y != 2 || I3.z != 3) {
+ return false;
+ }
+ I3.x = 2;
+ I3.y = 3;
+ I3.z = 4;
+ s.set_i32_3(I3);
+
+ I4 = s.get_i32_4();
+ if (I4.x != 1 || I4.y != 2 || I4.z != 3 || I4.w != 4) {
+ return false;
+ }
+ I4.x = 2;
+ I4.y = 3;
+ I4.z = 4;
+ I4.w = 5;
+ s.set_i32_4(I4);
+
+ Long2 L2 = s.get_u32_2();
+ if (L2.x != 1 || L2.y != 2) {
+ return false;
+ }
+ L2.x = 2;
+ L2.y = 3;
+ s.set_u32_2(L2);
+
+ Long3 L3 = s.get_u32_3();
+ if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+ return false;
+ }
+ L3.x = 2;
+ L3.y = 3;
+ L3.z = 4;
+ s.set_u32_3(L3);
+
+ Long4 L4 = s.get_u32_4();
+ if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+ return false;
+ }
+ L4.x = 2;
+ L4.y = 3;
+ L4.z = 4;
+ L4.w = 5;
+ s.set_u32_4(L4);
+
+ L2 = s.get_i64_2();
+ if (L2.x != 1 || L2.y != 2) {
+ return false;
+ }
+ L2.x = 2;
+ L2.y = 3;
+ s.set_i64_2(L2);
+
+ L3 = s.get_i64_3();
+ if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+ return false;
+ }
+ L3.x = 2;
+ L3.y = 3;
+ L3.z = 4;
+ s.set_i64_3(L3);
+
+ L4 = s.get_i64_4();
+ if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+ return false;
+ }
+ L4.x = 2;
+ L4.y = 3;
+ L4.z = 4;
+ L4.w = 5;
+ s.set_i64_4(L4);
+
+ L2 = s.get_u64_2();
+ if (L2.x != 1 || L2.y != 2) {
+ return false;
+ }
+ L2.x = 2;
+ L2.y = 3;
+ s.set_u64_2(L2);
+
+ L3 = s.get_u64_3();
+ if (L3.x != 1 || L3.y != 2 || L3.z != 3) {
+ return false;
+ }
+ L3.x = 2;
+ L3.y = 3;
+ L3.z = 4;
+ s.set_u64_3(L3);
+
+ L4 = s.get_u64_4();
+ if (L4.x != 1 || L4.y != 2 || L4.z != 3 || L4.w != 4) {
+ return false;
+ }
+ L4.x = 2;
+ L4.y = 3;
+ L4.z = 4;
+ L4.w = 5;
+ s.set_u64_4(L4);
+
+ return true;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_vector s = new ScriptC_vector(pRS, mRes, R.raw.vector);
+ pRS.setMessageHandler(mRsMessage);
+ if (!initializeGlobals(s)) {
+ result = -1;
+ } else {
+ s.invoke_vector_test();
+ pRS.finish();
+ waitForMessage();
+ }
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
index a7722c7..6151431 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
@@ -17,7 +17,6 @@
package com.android.rs.test;
import android.content.Context;
import android.renderscript.RenderScript.RSMessageHandler;
-import android.util.Log;
public class UnitTest extends Thread {
public String name;
@@ -67,7 +66,7 @@
result = -1;
break;
default:
- android.util.Log.v("RenderScript", "Unit test got unexpected message");
+ RSTest.log("Unit test got unexpected message");
return;
}
}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/vector.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/vector.rs
new file mode 100644
index 0000000..0430a2f
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/vector.rs
@@ -0,0 +1,198 @@
+#include "shared.rsh"
+
+// Testing vector types
+float2 f2 = { 1.0f, 2.0f };
+float3 f3 = { 1.0f, 2.0f, 3.0f };
+float4 f4 = { 1.0f, 2.0f, 3.0f, 4.0f };
+
+double2 d2 = { 1.0, 2.0 };
+double3 d3 = { 1.0, 2.0, 3.0 };
+double4 d4 = { 1.0, 2.0, 3.0, 4.0 };
+
+char2 i8_2 = { 1, 2 };
+char3 i8_3 = { 1, 2, 3 };
+char4 i8_4 = { 1, 2, 3, 4 };
+
+uchar2 u8_2 = { 1, 2 };
+uchar3 u8_3 = { 1, 2, 3 };
+uchar4 u8_4 = { 1, 2, 3, 4 };
+
+short2 i16_2 = { 1, 2 };
+short3 i16_3 = { 1, 2, 3 };
+short4 i16_4 = { 1, 2, 3, 4 };
+
+ushort2 u16_2 = { 1, 2 };
+ushort3 u16_3 = { 1, 2, 3 };
+ushort4 u16_4 = { 1, 2, 3, 4 };
+
+int2 i32_2 = { 1, 2 };
+int3 i32_3 = { 1, 2, 3 };
+int4 i32_4 = { 1, 2, 3, 4 };
+
+uint2 u32_2 = { 1, 2 };
+uint3 u32_3 = { 1, 2, 3 };
+uint4 u32_4 = { 1, 2, 3, 4 };
+
+long2 i64_2 = { 1, 2 };
+long3 i64_3 = { 1, 2, 3 };
+long4 i64_4 = { 1, 2, 3, 4 };
+
+ulong2 u64_2 = { 1, 2 };
+ulong3 u64_3 = { 1, 2, 3 };
+ulong4 u64_4 = { 1, 2, 3, 4 };
+
+static bool test_vector_types() {
+ bool failed = false;
+
+ rsDebug("Testing F32", 0);
+ _RS_ASSERT(f2.x == 2.99f);
+ _RS_ASSERT(f2.y == 3.99f);
+
+ _RS_ASSERT(f3.x == 2.99f);
+ _RS_ASSERT(f3.y == 3.99f);
+ _RS_ASSERT(f3.z == 4.99f);
+
+ _RS_ASSERT(f4.x == 2.99f);
+ _RS_ASSERT(f4.y == 3.99f);
+ _RS_ASSERT(f4.z == 4.99f);
+ _RS_ASSERT(f4.w == 5.99f);
+
+ rsDebug("Testing F64", 0);
+ _RS_ASSERT(d2.x == 2.99);
+ _RS_ASSERT(d2.y == 3.99);
+
+ _RS_ASSERT(d3.x == 2.99);
+ _RS_ASSERT(d3.y == 3.99);
+ _RS_ASSERT(d3.z == 4.99);
+
+ _RS_ASSERT(d4.x == 2.99);
+ _RS_ASSERT(d4.y == 3.99);
+ _RS_ASSERT(d4.z == 4.99);
+ _RS_ASSERT(d4.w == 5.99);
+
+ rsDebug("Testing I8", 0);
+ _RS_ASSERT(i8_2.x == 2);
+ _RS_ASSERT(i8_2.y == 3);
+
+ _RS_ASSERT(i8_3.x == 2);
+ _RS_ASSERT(i8_3.y == 3);
+ _RS_ASSERT(i8_3.z == 4);
+
+ _RS_ASSERT(i8_4.x == 2);
+ _RS_ASSERT(i8_4.y == 3);
+ _RS_ASSERT(i8_4.z == 4);
+ _RS_ASSERT(i8_4.w == 5);
+
+ rsDebug("Testing U8", 0);
+ _RS_ASSERT(u8_2.x == 2);
+ _RS_ASSERT(u8_2.y == 3);
+
+ _RS_ASSERT(u8_3.x == 2);
+ _RS_ASSERT(u8_3.y == 3);
+ _RS_ASSERT(u8_3.z == 4);
+
+ _RS_ASSERT(u8_4.x == 2);
+ _RS_ASSERT(u8_4.y == 3);
+ _RS_ASSERT(u8_4.z == 4);
+ _RS_ASSERT(u8_4.w == 5);
+
+ rsDebug("Testing I16", 0);
+ _RS_ASSERT(i16_2.x == 2);
+ _RS_ASSERT(i16_2.y == 3);
+
+ _RS_ASSERT(i16_3.x == 2);
+ _RS_ASSERT(i16_3.y == 3);
+ _RS_ASSERT(i16_3.z == 4);
+
+ _RS_ASSERT(i16_4.x == 2);
+ _RS_ASSERT(i16_4.y == 3);
+ _RS_ASSERT(i16_4.z == 4);
+ _RS_ASSERT(i16_4.w == 5);
+
+ rsDebug("Testing U16", 0);
+ _RS_ASSERT(u16_2.x == 2);
+ _RS_ASSERT(u16_2.y == 3);
+
+ _RS_ASSERT(u16_3.x == 2);
+ _RS_ASSERT(u16_3.y == 3);
+ _RS_ASSERT(u16_3.z == 4);
+
+ _RS_ASSERT(u16_4.x == 2);
+ _RS_ASSERT(u16_4.y == 3);
+ _RS_ASSERT(u16_4.z == 4);
+ _RS_ASSERT(u16_4.w == 5);
+
+ rsDebug("Testing I32", 0);
+ _RS_ASSERT(i32_2.x == 2);
+ _RS_ASSERT(i32_2.y == 3);
+
+ _RS_ASSERT(i32_3.x == 2);
+ _RS_ASSERT(i32_3.y == 3);
+ _RS_ASSERT(i32_3.z == 4);
+
+ _RS_ASSERT(i32_4.x == 2);
+ _RS_ASSERT(i32_4.y == 3);
+ _RS_ASSERT(i32_4.z == 4);
+ _RS_ASSERT(i32_4.w == 5);
+
+ rsDebug("Testing U32", 0);
+ _RS_ASSERT(u32_2.x == 2);
+ _RS_ASSERT(u32_2.y == 3);
+
+ _RS_ASSERT(u32_3.x == 2);
+ _RS_ASSERT(u32_3.y == 3);
+ _RS_ASSERT(u32_3.z == 4);
+
+ _RS_ASSERT(u32_4.x == 2);
+ _RS_ASSERT(u32_4.y == 3);
+ _RS_ASSERT(u32_4.z == 4);
+ _RS_ASSERT(u32_4.w == 5);
+
+ rsDebug("Testing I64", 0);
+ _RS_ASSERT(i64_2.x == 2);
+ _RS_ASSERT(i64_2.y == 3);
+
+ _RS_ASSERT(i64_3.x == 2);
+ _RS_ASSERT(i64_3.y == 3);
+ _RS_ASSERT(i64_3.z == 4);
+
+ _RS_ASSERT(i64_4.x == 2);
+ _RS_ASSERT(i64_4.y == 3);
+ _RS_ASSERT(i64_4.z == 4);
+ _RS_ASSERT(i64_4.w == 5);
+
+ rsDebug("Testing U64", 0);
+ _RS_ASSERT(u64_2.x == 2);
+ _RS_ASSERT(u64_2.y == 3);
+
+ _RS_ASSERT(u64_3.x == 2);
+ _RS_ASSERT(u64_3.y == 3);
+ _RS_ASSERT(u64_3.z == 4);
+
+ _RS_ASSERT(u64_4.x == 2);
+ _RS_ASSERT(u64_4.y == 3);
+ _RS_ASSERT(u64_4.z == 4);
+ _RS_ASSERT(u64_4.w == 5);
+
+ if (failed) {
+ rsDebug("test_vector FAILED", 0);
+ }
+ else {
+ rsDebug("test_vector PASSED", 0);
+ }
+
+ return failed;
+}
+
+void vector_test() {
+ bool failed = false;
+ failed |= test_vector_types();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 730bd71..b4ac929 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -2194,6 +2194,11 @@
}
}
}
+ // Handle the overlays
+ sp<AaptAssets> overlay = assets->getOverlay();
+ if (overlay.get()) {
+ return writeProguardForLayouts(keep, overlay);
+ }
return NO_ERROR;
}
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index 98f8529..fb2fc85 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -138,6 +138,10 @@
return "";
}
+ @LayoutlibDelegate
+ /*package*/ static String getScript(String locale) {
+ return "";
+ }
@LayoutlibDelegate
/*package*/ static String[] getISOLanguagesNative() {
@@ -186,7 +190,6 @@
// Used by DecimalFormatSymbols.
result.zeroDigit = '0';
- result.digit = '0';
result.decimalSeparator = '.';
result.groupingSeparator = ',';
result.patternSeparator = ' ';
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index e303638..98cade9 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -19,6 +19,8 @@
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIRS := res
+
LOCAL_MODULE := layoutlib-tests
LOCAL_MODULE_TAGS := optional
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/testdata/layout1.xml b/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml
similarity index 100%
rename from tools/layoutlib/bridge/tests/src/com/android/layoutlib/testdata/layout1.xml
rename to tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
index 96436fe..865a008 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
@@ -38,7 +38,7 @@
public void testXmlBlockParser() throws Exception {
XmlPullParser parser = ParserFactory.create(
- getClass().getResourceAsStream("com/android/layoutlib/testdata/layout1.xml"),
+ getClass().getResourceAsStream("/com/android/layoutlib/testdata/layout1.xml"),
"layout1.xml");
parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */);
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 65a64cd..894611b 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -30,9 +30,9 @@
Consequently this tool:
- parses the input JAR,
- modifies some of the classes directly using some bytecode manipulation,
-- filters some packages and removes some that we don't want to end in the output JAR,
+- filters some packages and removes those we don't want in the output JAR,
- injects some new classes,
-- and generates a modified JAR file that is suitable for the Android plugin
+- generates a modified JAR file that is suitable for the Android plugin
for Eclipse to perform rendering.
The ASM library is used to do the bytecode modification using its visitor pattern API.
@@ -63,7 +63,7 @@
To do that, the analyzer is created with a list of base classes to keep -- everything
that derives from these is kept. Currently the one such class is android.view.View:
-since we want to render layouts, anything that is sort of the view needs to be kept.
+since we want to render layouts, anything that is sort of a view needs to be kept.
The analyzer is also given a list of class names to keep in the output.
This is done using shell-like glob patterns that filter on the fully-qualified
@@ -90,6 +90,7 @@
- the classes to inject in the output JAR -- these classes are directly implemented
in layoutlib_create and will be used to interface with the renderer in Eclipse.
- specific methods to override (see method stubs details below).
+- specific methods for which to delegate calls.
- specific methods to remove based on their return type.
- specific classes to rename.
@@ -114,6 +115,9 @@
The code of the methods is then kept as-is, except for native methods which are
replaced by a stub. Methods that are to be overridden are also replaced by a stub.
+The transformed class is then fed through the DelegateClassAdapter to implement
+method delegates.
+
Finally fields are also visited and changed from protected/private to public.
@@ -131,8 +135,7 @@
method was native. We do not currently provide the parameters. The listener
can however specify the return value of the overridden method.
-An extension being worked on is to actually replace these listeners by
-direct calls to a delegate class, complete with parameters.
+This strategy is now obsolete and replaced by the method delegates.
- Strategies
@@ -160,6 +163,9 @@
by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
a listener on the method signature and can provide an implementation.
+This strategy is now obsolete and replaced by the method delegates.
+See strategy 5 below.
+
3- Renaming classes
@@ -195,6 +201,24 @@
bridge will provide its own implementation.
+5- Method Delegates
+
+This strategy is used to override method implementations.
+Given a method SomeClass.MethodName(), 1 or 2 methods are generated:
+a- A copy of the original method named SomeClass.MethodName_Original().
+ The content is the original method as-is from the reader.
+ This step is omitted if the method is native, since it has no Java implementation.
+b- A brand new implementation of SomeClass.MethodName() which calls to a
+ non-existing static method named SomeClass_Delegate.MethodName().
+ The implementation of this 'delegate' method is done in layoutlib_brigde.
+
+The delegate method is a static method.
+If the original method is non-static, the delegate method receives the original 'this'
+as its first argument. If the original method is an inner non-static method, it also
+receives the inner 'this' as the second argument.
+
+
+
- References -
--------------
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 5c60318..233f72ec 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -51,6 +51,8 @@
* Returns The list of methods to stub out. Each entry must be in the form
* "package.package.OuterClass$InnerClass#MethodName".
* The list can be empty but must not be null.
+ * <p/>
+ * This usage is deprecated. Please use method 'delegates' instead.
*/
public String[] getOverriddenMethods() {
return OVERRIDDEN_METHODS;
@@ -158,6 +160,7 @@
/**
* The list of methods to stub out. Each entry must be in the form
* "package.package.OuterClass$InnerClass#MethodName".
+ * This usage is deprecated. Please use method 'delegates' instead.
*/
private final static String[] OVERRIDDEN_METHODS = new String[] {
};
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
index 9cba8a0..49ddf1d 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
@@ -31,6 +31,11 @@
*/
public class DelegateClassAdapter extends ClassAdapter {
+ /** Suffix added to original methods. */
+ private static final String ORIGINAL_SUFFIX = "_Original";
+ private static String CONSTRUCTOR = "<init>";
+ private static String CLASS_INIT = "<clinit>";
+
public final static String ALL_NATIVES = "<<all_natives>>";
private final String mClassName;
@@ -73,22 +78,55 @@
boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) ||
mDelegateMethods.contains(name);
- if (useDelegate) {
- // remove native
- access = access & ~Opcodes.ACC_NATIVE;
+ if (!useDelegate) {
+ // Not creating a delegate for this method, pass it as-is from the reader
+ // to the writer.
+ return super.visitMethod(access, name, desc, signature, exceptions);
}
- MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
if (useDelegate) {
- DelegateMethodAdapter a = new DelegateMethodAdapter(mLog, mw, mClassName,
- name, desc, isStatic);
- if (isNative) {
- // A native has no code to visit, so we need to generate it directly.
- a.generateCode();
- } else {
- return a;
+ if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
+ // We don't currently support generating delegates for constructors.
+ throw new UnsupportedOperationException(
+ String.format(
+ "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$
+ mClassName, name, desc));
}
}
- return mw;
+
+ if (isNative) {
+ // Remove native flag
+ access = access & ~Opcodes.ACC_NATIVE;
+ MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions);
+
+ DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
+ mLog, null /*mwOriginal*/, mwDelegate, mClassName, name, desc, isStatic);
+
+ // A native has no code to visit, so we need to generate it directly.
+ a.generateDelegateCode();
+
+ return mwDelegate;
+ }
+
+ // Given a non-native SomeClass.MethodName(), we want to generate 2 methods:
+ // - A copy of the original method named SomeClass.MethodName_Original().
+ // The content is the original method as-is from the reader.
+ // - A brand new implementation of SomeClass.MethodName() which calls to a
+ // non-existing method named SomeClass_Delegate.MethodName().
+ // The implementation of this 'delegate' method is done in layoutlib_brigde.
+
+ int accessDelegate = access;
+ // change access to public for the original one
+ access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+ access |= Opcodes.ACC_PUBLIC;
+
+ MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
+ desc, signature, exceptions);
+ MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name,
+ desc, signature, exceptions);
+
+ DelegateMethodAdapter2 a = new DelegateMethodAdapter2(
+ mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic);
+ return a;
}
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
deleted file mode 100644
index 8d7f016..0000000
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.util.ArrayList;
-
-/**
- * This method adapter rewrites a method by discarding the original code and generating
- * a call to a delegate. Original annotations are passed along unchanged.
- * <p/>
- * Calls are delegated to a class named <code><className>_Delegate</code> with
- * static methods matching the methods to be overridden here. The methods have the
- * same return type. The argument type list is the same except the "this" reference is
- * passed first for non-static methods.
- * <p/>
- * A new annotation is added.
- * <p/>
- * Note that native methods have, by definition, no code so there's nothing a visitor
- * can visit. That means the caller must call {@link #generateCode()} directly for
- * a native and use the visitor pattern for non-natives.
- * <p/>
- * Instances of this class are not re-usable. You need a new instance for each method.
- */
-class DelegateMethodAdapter implements MethodVisitor {
-
- /**
- * Suffix added to delegate classes.
- */
- public static final String DELEGATE_SUFFIX = "_Delegate";
-
- private static String CONSTRUCTOR = "<init>";
- private static String CLASS_INIT = "<clinit>";
-
- /** The parent method writer */
- private MethodVisitor mParentVisitor;
- /** Flag to output the first line number. */
- private boolean mOutputFirstLineNumber = true;
- /** The original method descriptor (return type + argument types.) */
- private String mDesc;
- /** True if the original method is static. */
- private final boolean mIsStatic;
- /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */
- private final String mClassName;
- /** The method name. */
- private final String mMethodName;
- /** Logger object. */
- private final Log mLog;
- /** True if {@link #visitCode()} has been invoked. */
- private boolean mVisitCodeCalled;
-
- /**
- * Creates a new {@link DelegateMethodAdapter} that will transform this method
- * into a delegate call.
- * <p/>
- * See {@link DelegateMethodAdapter} for more details.
- *
- * @param log The logger object. Must not be null.
- * @param mv the method visitor to which this adapter must delegate calls.
- * @param className The internal class name of the class to visit,
- * e.g. <code>com/android/SomeClass$InnerClass</code>.
- * @param methodName The simple name of the method.
- * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} +
- * {@link Type#getArgumentTypes(String)})
- * @param isStatic True if the method is declared static.
- */
- public DelegateMethodAdapter(Log log,
- MethodVisitor mv,
- String className,
- String methodName,
- String desc,
- boolean isStatic) {
- mLog = log;
- mParentVisitor = mv;
- mClassName = className;
- mMethodName = methodName;
- mDesc = desc;
- mIsStatic = isStatic;
-
- if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
- // We're going to simplify by not supporting constructors.
- // The only trick with a constructor is to find the proper super constructor
- // and call it (and deciding if we should mirror the original method call to
- // a custom constructor or call a default one.)
- throw new UnsupportedOperationException(
- String.format("Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)",
- className, methodName, desc));
- }
- }
-
- /**
- * Generates the new code for the method.
- * <p/>
- * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
- * (since they have no code to visit).
- * <p/>
- * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
- * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern
- * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
- * this method will be invoked from {@link MethodVisitor#visitEnd()}.
- */
- public void generateCode() {
- /*
- * The goal is to generate a call to a static delegate method.
- * If this method is non-static, the first parameter will be 'this'.
- * All the parameters must be passed and then the eventual return type returned.
- *
- * Example, let's say we have a method such as
- * public void method_1(int a, Object b, ArrayList<String> c) { ... }
- *
- * We'll want to create a body that calls a delegate method like this:
- * TheClass_Delegate.method_1(this, a, b, c);
- *
- * If the method is non-static and the class name is an inner class (e.g. has $ in its
- * last segment), we want to push the 'this' of the outer class first:
- * OuterClass_InnerClass_Delegate.method_1(
- * OuterClass.this,
- * OuterClass$InnerClass.this,
- * a, b, c);
- *
- * Only one level of inner class is supported right now, for simplicity and because
- * we don't need more.
- *
- * The generated class name is the current class name with "_Delegate" appended to it.
- * One thing to realize is that we don't care about generics -- since generic types
- * are erased at runtime, they have no influence on the method name being called.
- */
-
- // Add our annotation
- AnnotationVisitor aw = mParentVisitor.visitAnnotation(
- Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(),
- true); // visible at runtime
- aw.visitEnd();
-
- if (!mVisitCodeCalled) {
- // If this is a direct call to generateCode() as done by DelegateClassAdapter
- // for natives, visitCode() hasn't been called yet.
- mParentVisitor.visitCode();
- mVisitCodeCalled = true;
- }
-
- ArrayList<Type> paramTypes = new ArrayList<Type>();
- String delegateClassName = mClassName + DELEGATE_SUFFIX;
- boolean pushedArg0 = false;
- int maxStack = 0;
-
- // For an instance method (e.g. non-static), push the 'this' preceded
- // by the 'this' of any outer class, if any.
- if (!mIsStatic) {
- // Check if the last segment of the class name has inner an class.
- // Right now we only support one level of inner classes.
- int slash = mClassName.lastIndexOf('/');
- int dol = mClassName.lastIndexOf('$');
- if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
- String outerClass = mClassName.substring(0, dol);
- Type outerType = Type.getObjectType(outerClass);
-
- // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
- delegateClassName = delegateClassName.replace('$', '_');
-
- // The first-level inner class has a package-protected member called 'this$0'
- // that points to the outer class.
-
- // Push this.getField("this$0") on the call stack.
- mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
- mParentVisitor.visitFieldInsn(Opcodes.GETFIELD,
- mClassName, // class where the field is defined
- "this$0", // field name
- outerType.getDescriptor()); // type of the field
- maxStack++;
- paramTypes.add(outerType);
- }
-
- // Push "this" for the instance method, which is always ALOAD 0
- mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
- maxStack++;
- pushedArg0 = true;
- paramTypes.add(Type.getObjectType(mClassName));
- }
-
- // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
- Type[] argTypes = Type.getArgumentTypes(mDesc);
- int maxLocals = pushedArg0 ? 1 : 0;
- for (Type t : argTypes) {
- int size = t.getSize();
- mParentVisitor.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
- maxLocals += size;
- maxStack += size;
- paramTypes.add(t);
- }
-
- // Construct the descriptor of the delegate based on the parameters
- // we pushed on the call stack. The return type remains unchanged.
- String desc = Type.getMethodDescriptor(
- Type.getReturnType(mDesc),
- paramTypes.toArray(new Type[paramTypes.size()]));
-
- // Invoke the static delegate
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- delegateClassName,
- mMethodName,
- desc);
-
- Type returnType = Type.getReturnType(mDesc);
- mParentVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
-
- mParentVisitor.visitMaxs(maxStack, maxLocals);
- mParentVisitor.visitEnd();
-
- // For debugging now. Maybe we should collect these and store them in
- // a text file for helping create the delegates. We could also compare
- // the text file to a golden and break the build on unsupported changes
- // or regressions. Even better we could fancy-print something that looks
- // like the expected Java method declaration.
- mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
- }
-
- /* Pass down to visitor writer. In this implementation, either do nothing. */
- public void visitCode() {
- mVisitCodeCalled = true;
- mParentVisitor.visitCode();
- }
-
- /*
- * visitMaxs is called just before visitEnd if there was any code to rewrite.
- * Skip the original.
- */
- public void visitMaxs(int maxStack, int maxLocals) {
- }
-
- /**
- * End of visiting. Generate the messaging code.
- */
- public void visitEnd() {
- generateCode();
- }
-
- /* Writes all annotation from the original method. */
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- return mParentVisitor.visitAnnotation(desc, visible);
- }
-
- /* Writes all annotation default values from the original method. */
- public AnnotationVisitor visitAnnotationDefault() {
- return mParentVisitor.visitAnnotationDefault();
- }
-
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
- }
-
- /* Writes all attributes from the original method. */
- public void visitAttribute(Attribute attr) {
- mParentVisitor.visitAttribute(attr);
- }
-
- /*
- * Only writes the first line number present in the original code so that source
- * viewers can direct to the correct method, even if the content doesn't match.
- */
- public void visitLineNumber(int line, Label start) {
- if (mOutputFirstLineNumber) {
- mParentVisitor.visitLineNumber(line, start);
- mOutputFirstLineNumber = false;
- }
- }
-
- public void visitInsn(int opcode) {
- // Skip original code.
- }
-
- public void visitLabel(Label label) {
- // Skip original code.
- }
-
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- // Skip original code.
- }
-
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- // Skip original code.
- }
-
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- // Skip original code.
- }
-
- public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
- // Skip original code.
- }
-
- public void visitIincInsn(int var, int increment) {
- // Skip original code.
- }
-
- public void visitIntInsn(int opcode, int operand) {
- // Skip original code.
- }
-
- public void visitJumpInsn(int opcode, Label label) {
- // Skip original code.
- }
-
- public void visitLdcInsn(Object cst) {
- // Skip original code.
- }
-
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- // Skip original code.
- }
-
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- // Skip original code.
- }
-
- public void visitMultiANewArrayInsn(String desc, int dims) {
- // Skip original code.
- }
-
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
- // Skip original code.
- }
-
- public void visitTypeInsn(int opcode, String type) {
- // Skip original code.
- }
-
- public void visitVarInsn(int opcode, int var) {
- // Skip original code.
- }
-
-}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
new file mode 100644
index 0000000..ac4ae6d
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+
+/**
+ * This method adapter generates delegate methods.
+ * <p/>
+ * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods:
+ * <ul>
+ * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}.
+ * The content is the original method as-is from the reader.
+ * This step is omitted if the method is native, since it has no Java implementation.
+ * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a
+ * non-existing method named {@code SomeClass_Delegate.MethodName()}.
+ * The implementation of this 'delegate' method is done in layoutlib_brigde.
+ * </ul>
+ * A method visitor is generally constructed to generate a single method; however
+ * here we might want to generate one or two depending on the context. To achieve
+ * that, the visitor here generates the 'original' method and acts as a no-op if
+ * no such method exists (e.g. when the original is a native method).
+ * The delegate method is generated after the {@code visitEnd} of the original method
+ * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()}
+ * for native methods.
+ * <p/>
+ * When generating the 'delegate', the implementation generates a call to a class
+ * class named <code><className>_Delegate</code> with static methods matching
+ * the methods to be overridden here. The methods have the same return type.
+ * The argument type list is the same except the "this" reference is passed first
+ * for non-static methods.
+ * <p/>
+ * A new annotation is added to these 'delegate' methods so that we can easily find them
+ * for automated testing.
+ * <p/>
+ * This class isn't intended to be generic or reusable.
+ * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing
+ * the two method writers for the original and the delegate class, as needed, with their
+ * expected names.
+ * <p/>
+ * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for
+ * a native and use the visitor pattern for non-natives.
+ * Note that native methods have, by definition, no code so there's nothing a visitor
+ * can visit.
+ * <p/>
+ * Instances of this class are not re-usable.
+ * The class adapter creates a new instance for each method.
+ */
+class DelegateMethodAdapter2 implements MethodVisitor {
+
+ /** Suffix added to delegate classes. */
+ public static final String DELEGATE_SUFFIX = "_Delegate";
+
+ /** The parent method writer to copy of the original method.
+ * Null when dealing with a native original method. */
+ private MethodVisitor mOrgWriter;
+ /** The parent method writer to generate the delegating method. Never null. */
+ private MethodVisitor mDelWriter;
+ /** The original method descriptor (return type + argument types.) */
+ private String mDesc;
+ /** True if the original method is static. */
+ private final boolean mIsStatic;
+ /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */
+ private final String mClassName;
+ /** The method name. */
+ private final String mMethodName;
+ /** Logger object. */
+ private final Log mLog;
+
+ /** Array used to capture the first line number information from the original method
+ * and duplicate it in the delegate. */
+ private Object[] mDelegateLineNumber;
+
+ /**
+ * Creates a new {@link DelegateMethodAdapter2} that will transform this method
+ * into a delegate call.
+ * <p/>
+ * See {@link DelegateMethodAdapter2} for more details.
+ *
+ * @param log The logger object. Must not be null.
+ * @param mvOriginal The parent method writer to copy of the original method.
+ * Must be {@code null} when dealing with a native original method.
+ * @param mvDelegate The parent method writer to generate the delegating method.
+ * Must never be null.
+ * @param className The internal class name of the class to visit,
+ * e.g. <code>com/android/SomeClass$InnerClass</code>.
+ * @param methodName The simple name of the method.
+ * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} +
+ * {@link Type#getArgumentTypes(String)})
+ * @param isStatic True if the method is declared static.
+ */
+ public DelegateMethodAdapter2(Log log,
+ MethodVisitor mvOriginal,
+ MethodVisitor mvDelegate,
+ String className,
+ String methodName,
+ String desc,
+ boolean isStatic) {
+ mLog = log;
+ mOrgWriter = mvOriginal;
+ mDelWriter = mvDelegate;
+ mClassName = className;
+ mMethodName = methodName;
+ mDesc = desc;
+ mIsStatic = isStatic;
+ }
+
+ /**
+ * Generates the new code for the method.
+ * <p/>
+ * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
+ * (since they have no code to visit).
+ * <p/>
+ * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
+ * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern
+ * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
+ * this method will be invoked from {@link MethodVisitor#visitEnd()}.
+ */
+ public void generateDelegateCode() {
+ /*
+ * The goal is to generate a call to a static delegate method.
+ * If this method is non-static, the first parameter will be 'this'.
+ * All the parameters must be passed and then the eventual return type returned.
+ *
+ * Example, let's say we have a method such as
+ * public void myMethod(int a, Object b, ArrayList<String> c) { ... }
+ *
+ * We'll want to create a body that calls a delegate method like this:
+ * TheClass_Delegate.myMethod(this, a, b, c);
+ *
+ * If the method is non-static and the class name is an inner class (e.g. has $ in its
+ * last segment), we want to push the 'this' of the outer class first:
+ * OuterClass_InnerClass_Delegate.myMethod(
+ * OuterClass.this,
+ * OuterClass$InnerClass.this,
+ * a, b, c);
+ *
+ * Only one level of inner class is supported right now, for simplicity and because
+ * we don't need more.
+ *
+ * The generated class name is the current class name with "_Delegate" appended to it.
+ * One thing to realize is that we don't care about generics -- since generic types
+ * are erased at build time, they have no influence on the method name being called.
+ */
+
+ // Add our annotation
+ AnnotationVisitor aw = mDelWriter.visitAnnotation(
+ Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(),
+ true); // visible at runtime
+ if (aw != null) {
+ aw.visitEnd();
+ }
+
+ mDelWriter.visitCode();
+
+ if (mDelegateLineNumber != null) {
+ Object[] p = mDelegateLineNumber;
+ mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]);
+ }
+
+ ArrayList<Type> paramTypes = new ArrayList<Type>();
+ String delegateClassName = mClassName + DELEGATE_SUFFIX;
+ boolean pushedArg0 = false;
+ int maxStack = 0;
+
+ // For an instance method (e.g. non-static), push the 'this' preceded
+ // by the 'this' of any outer class, if any.
+ if (!mIsStatic) {
+ // Check if the last segment of the class name has inner an class.
+ // Right now we only support one level of inner classes.
+ int slash = mClassName.lastIndexOf('/');
+ int dol = mClassName.lastIndexOf('$');
+ if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
+ String outerClass = mClassName.substring(0, dol);
+ Type outerType = Type.getObjectType(outerClass);
+
+ // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
+ delegateClassName = delegateClassName.replace('$', '_');
+
+ // The first-level inner class has a package-protected member called 'this$0'
+ // that points to the outer class.
+
+ // Push this.getField("this$0") on the call stack.
+ mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
+ mDelWriter.visitFieldInsn(Opcodes.GETFIELD,
+ mClassName, // class where the field is defined
+ "this$0", // field name
+ outerType.getDescriptor()); // type of the field
+ maxStack++;
+ paramTypes.add(outerType);
+ }
+
+ // Push "this" for the instance method, which is always ALOAD 0
+ mDelWriter.visitVarInsn(Opcodes.ALOAD, 0);
+ maxStack++;
+ pushedArg0 = true;
+ paramTypes.add(Type.getObjectType(mClassName));
+ }
+
+ // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
+ Type[] argTypes = Type.getArgumentTypes(mDesc);
+ int maxLocals = pushedArg0 ? 1 : 0;
+ for (Type t : argTypes) {
+ int size = t.getSize();
+ mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
+ maxLocals += size;
+ maxStack += size;
+ paramTypes.add(t);
+ }
+
+ // Construct the descriptor of the delegate based on the parameters
+ // we pushed on the call stack. The return type remains unchanged.
+ String desc = Type.getMethodDescriptor(
+ Type.getReturnType(mDesc),
+ paramTypes.toArray(new Type[paramTypes.size()]));
+
+ // Invoke the static delegate
+ mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC,
+ delegateClassName,
+ mMethodName,
+ desc);
+
+ Type returnType = Type.getReturnType(mDesc);
+ mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+
+ mDelWriter.visitMaxs(maxStack, maxLocals);
+ mDelWriter.visitEnd();
+
+ // For debugging now. Maybe we should collect these and store them in
+ // a text file for helping create the delegates. We could also compare
+ // the text file to a golden and break the build on unsupported changes
+ // or regressions. Even better we could fancy-print something that looks
+ // like the expected Java method declaration.
+ mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
+ }
+
+ /* Pass down to visitor writer. In this implementation, either do nothing. */
+ public void visitCode() {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitCode();
+ }
+ }
+
+ /*
+ * visitMaxs is called just before visitEnd if there was any code to rewrite.
+ */
+ public void visitMaxs(int maxStack, int maxLocals) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ /** End of visiting. Generate the delegating code. */
+ public void visitEnd() {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitEnd();
+ }
+ generateDelegateCode();
+ }
+
+ /* Writes all annotation from the original method. */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (mOrgWriter != null) {
+ return mOrgWriter.visitAnnotation(desc, visible);
+ } else {
+ return null;
+ }
+ }
+
+ /* Writes all annotation default values from the original method. */
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (mOrgWriter != null) {
+ return mOrgWriter.visitAnnotationDefault();
+ } else {
+ return null;
+ }
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
+ boolean visible) {
+ if (mOrgWriter != null) {
+ return mOrgWriter.visitParameterAnnotation(parameter, desc, visible);
+ } else {
+ return null;
+ }
+ }
+
+ /* Writes all attributes from the original method. */
+ public void visitAttribute(Attribute attr) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitAttribute(attr);
+ }
+ }
+
+ /*
+ * Only writes the first line number present in the original code so that source
+ * viewers can direct to the correct method, even if the content doesn't match.
+ */
+ public void visitLineNumber(int line, Label start) {
+ // Capture the first line values for the new delegate method
+ if (mDelegateLineNumber == null) {
+ mDelegateLineNumber = new Object[] { line, start };
+ }
+ if (mOrgWriter != null) {
+ mOrgWriter.visitLineNumber(line, start);
+ }
+ }
+
+ public void visitInsn(int opcode) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitInsn(opcode);
+ }
+ }
+
+ public void visitLabel(Label label) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitLabel(label);
+ }
+ }
+
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitFrame(type, nLocal, local, nStack, stack);
+ }
+ }
+
+ public void visitIincInsn(int var, int increment) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitIincInsn(var, increment);
+ }
+ }
+
+ public void visitIntInsn(int opcode, int operand) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitIntInsn(opcode, operand);
+ }
+ }
+
+ public void visitJumpInsn(int opcode, Label label) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitJumpInsn(opcode, label);
+ }
+ }
+
+ public void visitLdcInsn(Object cst) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitLdcInsn(cst);
+ }
+ }
+
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+ }
+
+ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ public void visitTypeInsn(int opcode, String type) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitTypeInsn(opcode, type);
+ }
+ }
+
+ public void visitVarInsn(int opcode, int var) {
+ if (mOrgWriter != null) {
+ mOrgWriter.visitVarInsn(opcode, var);
+ }
+ }
+
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
index 9a57a4a..d70d028 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
@@ -31,7 +31,7 @@
private static String CONSTRUCTOR = "<init>";
private static String CLASS_INIT = "<clinit>";
-
+
/** The parent method writer */
private MethodVisitor mParentVisitor;
/** The method return type. Can be null. */
@@ -40,7 +40,7 @@
private String mInvokeSignature;
/** Flag to output the first line number. */
private boolean mOutputFirstLineNumber = true;
- /** Flag that is true when implementing a constructor, to accept all original
+ /** Flag that is true when implementing a constructor, to accept all original
* code calling the original super constructor. */
private boolean mIsInitMethod = false;
@@ -55,12 +55,12 @@
mInvokeSignature = invokeSignature;
mIsStatic = isStatic;
mIsNative = isNative;
-
+
if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
mIsInitMethod = true;
}
}
-
+
private void generateInvoke() {
/* Generates the code:
* OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
@@ -188,7 +188,7 @@
}
mParentVisitor.visitMaxs(maxStack, maxLocals);
}
-
+
/**
* End of visiting.
* For non-constructor, generate the messaging code and the return statement
@@ -250,6 +250,7 @@
generatePop();
generateInvoke();
mMessageGenerated = true;
+ //$FALL-THROUGH$
default:
mParentVisitor.visitInsn(opcode);
}
@@ -346,5 +347,5 @@
mParentVisitor.visitVarInsn(opcode, var);
}
}
-
+
}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index e8b3ea8..6e120ce 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -130,7 +130,7 @@
}
/**
- * {@link DelegateMethodAdapter} does not support overriding constructors yet,
+ * {@link DelegateMethodAdapter2} does not support overriding constructors yet,
* so this should fail with an {@link UnsupportedOperationException}.
*
* Although not tested here, the message of the exception should contain the
@@ -202,6 +202,7 @@
// We'll delegate the "get" method of both the inner and outer class.
HashSet<String> delegateMethods = new HashSet<String>();
delegateMethods.add("get");
+ delegateMethods.add("privateMethod");
// Generate the delegate for the outer class.
ClassWriter cwOuter = new ClassWriter(0 /*flags*/);
@@ -234,6 +235,25 @@
// The original Outer.get returns 1+10+20,
// but the delegate makes it return 4+10+20
assertEquals(4+10+20, callGet(o2, 10, 20));
+ assertEquals(1+10+20, callGet_Original(o2, 10, 20));
+
+ // The original Outer has a private method that is
+ // delegated. We should be able to call both the delegate
+ // and the original (which is now public).
+ assertEquals("outerPrivateMethod",
+ callMethod(o2, "privateMethod_Original", false /*makePublic*/));
+
+ // The original method is private, so by default we can't access it
+ boolean gotIllegalAccessException = false;
+ try {
+ callMethod(o2, "privateMethod", false /*makePublic*/);
+ } catch(IllegalAccessException e) {
+ gotIllegalAccessException = true;
+ }
+ assertTrue(gotIllegalAccessException);
+ // Try again, but now making it accessible
+ assertEquals("outerPrivate_Delegate",
+ callMethod(o2, "privateMethod", true /*makePublic*/));
// Check the inner class. Since it's not a static inner class, we need
// to use the hidden constructor that takes the outer class as first parameter.
@@ -246,6 +266,7 @@
// The original Inner.get returns 3+10+20,
// but the delegate makes it return 6+10+20
assertEquals(6+10+20, callGet(i2, 10, 20));
+ assertEquals(3+10+20, callGet_Original(i2, 10, 20));
}
};
cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray());
@@ -319,7 +340,7 @@
}
/**
- * Accesses {@link OuterClass#get()} or {@link InnerClass#get() }via reflection.
+ * Accesses {@link OuterClass#get} or {@link InnerClass#get}via reflection.
*/
public int callGet(Object instance, int a, long b) throws Exception {
Method m = instance.getClass().getMethod("get",
@@ -330,6 +351,39 @@
}
/**
+ * Accesses the "_Original" methods for {@link OuterClass#get}
+ * or {@link InnerClass#get}via reflection.
+ */
+ public int callGet_Original(Object instance, int a, long b) throws Exception {
+ Method m = instance.getClass().getMethod("get_Original",
+ new Class<?>[] { int.class, long.class } );
+
+ Object result = m.invoke(instance, new Object[] { a, b });
+ return ((Integer) result).intValue();
+ }
+
+ /**
+ * Accesses the any declared method that takes no parameter via reflection.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T callMethod(Object instance, String methodName, boolean makePublic) throws Exception {
+ Method m = instance.getClass().getDeclaredMethod(methodName, (Class<?>[])null);
+
+ boolean wasAccessible = m.isAccessible();
+ if (makePublic && !wasAccessible) {
+ m.setAccessible(true);
+ }
+
+ Object result = m.invoke(instance, (Object[])null);
+
+ if (makePublic && !wasAccessible) {
+ m.setAccessible(false);
+ }
+
+ return (T) result;
+ }
+
+ /**
* Accesses {@link ClassWithNative#add(int, int)} via reflection.
*/
public int callAdd(Object instance, int a, int b) throws Exception {
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
index 9dc2f69..f083e76 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java
@@ -39,10 +39,15 @@
public InnerClass() {
}
- // Inner.get returns 1+2=3 + a + b
+ // Inner.get returns 2 + 1 + a + b
public int get(int a, long b) {
return 2 + mOuterValue + a + (int) b;
}
}
+
+ @SuppressWarnings("unused")
+ private String privateMethod() {
+ return "outerPrivateMethod";
+ }
}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
index 3252d87..774be8e 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java
@@ -26,5 +26,9 @@
public static int get(OuterClass instance, int a, long b) {
return 4 + a + (int) b;
}
+
+ public static String privateMethod(OuterClass instance) {
+ return "outerPrivate_Delegate";
+ }
}
diff --git a/voip/java/android/net/sip/ISipSessionListener.aidl b/voip/java/android/net/sip/ISipSessionListener.aidl
index 5920bca..690700c 100644
--- a/voip/java/android/net/sip/ISipSessionListener.aidl
+++ b/voip/java/android/net/sip/ISipSessionListener.aidl
@@ -72,6 +72,14 @@
void onCallBusy(in ISipSession session);
/**
+ * Called when the call is being transferred to a new one.
+ *
+ * @param newSession the new session that the call will be transferred to
+ * @param sessionDescription the new peer's session description
+ */
+ void onCallTransferring(in ISipSession newSession, String sessionDescription);
+
+ /**
* Called when an error occurs during session initialization and
* termination.
*
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index b46f8268..c1affa6 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -26,6 +26,7 @@
import android.net.wifi.WifiManager;
import android.os.Message;
import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
@@ -170,6 +171,7 @@
private SipProfile mLocalProfile;
private SipAudioCall.Listener mListener;
private SipSession mSipSession;
+ private SipSession mTransferringSession;
private long mSessionId = System.currentTimeMillis();
private String mPeerSd;
@@ -347,6 +349,27 @@
}
}
+ private synchronized void transferToNewSession() {
+ if (mTransferringSession == null) return;
+ SipSession origin = mSipSession;
+ mSipSession = mTransferringSession;
+ mTransferringSession = null;
+
+ // stop the replaced call.
+ if (mAudioStream != null) {
+ mAudioStream.join(null);
+ } else {
+ try {
+ mAudioStream = new AudioStream(InetAddress.getByName(
+ getLocalIp()));
+ } catch (Throwable t) {
+ Log.i(TAG, "transferToNewSession(): " + t);
+ }
+ }
+ if (origin != null) origin.endCall();
+ startAudio();
+ }
+
private SipSession.Listener createListener() {
return new SipSession.Listener() {
@Override
@@ -378,6 +401,7 @@
@Override
public void onRinging(SipSession session,
SipProfile peerProfile, String sessionDescription) {
+ // this callback is triggered only for reinvite.
synchronized (SipAudioCall.this) {
if ((mSipSession == null) || !mInCall
|| !session.getCallId().equals(
@@ -404,6 +428,13 @@
mPeerSd = sessionDescription;
Log.v(TAG, "onCallEstablished()" + mPeerSd);
+ // TODO: how to notify the UI that the remote party is changed
+ if ((mTransferringSession != null)
+ && (session == mTransferringSession)) {
+ transferToNewSession();
+ return;
+ }
+
Listener listener = mListener;
if (listener != null) {
try {
@@ -420,7 +451,17 @@
@Override
public void onCallEnded(SipSession session) {
- Log.d(TAG, "sip call ended: " + session);
+ Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+ // reset the trasnferring session if it is the one.
+ if (session == mTransferringSession) {
+ mTransferringSession = null;
+ return;
+ }
+ // or ignore the event if the original session is being
+ // transferred to the new one.
+ if ((mTransferringSession != null) ||
+ (session != mSipSession)) return;
+
Listener listener = mListener;
if (listener != null) {
try {
@@ -489,6 +530,22 @@
public void onRegistrationDone(SipSession session, int duration) {
// irrelevant
}
+
+ @Override
+ public void onCallTransferring(SipSession newSession,
+ String sessionDescription) {
+ Log.v(TAG, "onCallTransferring mSipSession:"
+ + mSipSession + " newSession:" + newSession);
+ mTransferringSession = newSession;
+ // session changing request
+ try {
+ String answer = createAnswer(sessionDescription).encode();
+ newSession.answerCall(answer, SESSION_TIMEOUT);
+ } catch (Throwable e) {
+ Log.e(TAG, "onCallTransferring()", e);
+ newSession.endCall();
+ }
+ }
};
}
@@ -675,6 +732,7 @@
}
private SimpleSessionDescription createAnswer(String offerSd) {
+ if (TextUtils.isEmpty(offerSd)) return createOffer();
SimpleSessionDescription offer =
new SimpleSessionDescription(offerSd);
SimpleSessionDescription answer =
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 5629b3c..5ba1626 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -160,6 +160,17 @@
}
/**
+ * Called when the call is being transferred to a new one.
+ *
+ * @hide
+ * @param newSession the new session that the call will be transferred to
+ * @param sessionDescription the new peer's session description
+ */
+ public void onCallTransferring(SipSession newSession,
+ String sessionDescription) {
+ }
+
+ /**
* Called when an error occurs during session initialization and
* termination.
*
@@ -489,6 +500,16 @@
}
}
+ public void onCallTransferring(ISipSession session,
+ String sessionDescription) {
+ if (mListener != null) {
+ mListener.onCallTransferring(
+ new SipSession(session, SipSession.this.mListener),
+ sessionDescription);
+
+ }
+ }
+
public void onCallChangeFailed(ISipSession session, int errorCode,
String message) {
if (mListener != null) {
diff --git a/voip/java/android/net/sip/SipSessionAdapter.java b/voip/java/android/net/sip/SipSessionAdapter.java
index 86aca37..f538983 100644
--- a/voip/java/android/net/sip/SipSessionAdapter.java
+++ b/voip/java/android/net/sip/SipSessionAdapter.java
@@ -42,6 +42,10 @@
public void onCallBusy(ISipSession session) {
}
+ public void onCallTransferring(ISipSession session,
+ String sessionDescription) {
+ }
+
public void onCallChangeFailed(ISipSession session, int errorCode,
String message) {
}
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 4ee86b6..c031bc1 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -71,6 +71,7 @@
class SipHelper {
private static final String TAG = SipHelper.class.getSimpleName();
private static final boolean DEBUG = true;
+ private static final boolean DEBUG_PING = false;
private SipStack mSipStack;
private SipProvider mSipProvider;
@@ -149,9 +150,17 @@
private ContactHeader createContactHeader(SipProfile profile)
throws ParseException, SipException {
- ListeningPoint lp = getListeningPoint();
- SipURI contactURI =
- createSipUri(profile.getUserName(), profile.getProtocol(), lp);
+ return createContactHeader(profile, null, 0);
+ }
+
+ private ContactHeader createContactHeader(SipProfile profile,
+ String ip, int port) throws ParseException,
+ SipException {
+ SipURI contactURI = (ip == null)
+ ? createSipUri(profile.getUserName(), profile.getProtocol(),
+ getListeningPoint())
+ : createSipUri(profile.getUserName(), profile.getProtocol(),
+ ip, port);
Address contactAddress = mAddressFactory.createAddress(contactURI);
contactAddress.setDisplayName(profile.getDisplayName());
@@ -167,9 +176,14 @@
private SipURI createSipUri(String username, String transport,
ListeningPoint lp) throws ParseException {
- SipURI uri = mAddressFactory.createSipURI(username, lp.getIPAddress());
+ return createSipUri(username, transport, lp.getIPAddress(), lp.getPort());
+ }
+
+ private SipURI createSipUri(String username, String transport,
+ String ip, int port) throws ParseException {
+ SipURI uri = mAddressFactory.createSipURI(username, ip);
try {
- uri.setPort(lp.getPort());
+ uri.setPort(port);
uri.setTransportParam(transport);
} catch (InvalidArgumentException e) {
throw new RuntimeException(e);
@@ -177,17 +191,19 @@
return uri;
}
- public ClientTransaction sendKeepAlive(SipProfile userProfile, String tag)
- throws SipException {
+ public ClientTransaction sendOptions(SipProfile caller, SipProfile callee,
+ String tag) throws SipException {
try {
- Request request = createRequest(Request.OPTIONS, userProfile, tag);
+ Request request = (caller == callee)
+ ? createRequest(Request.OPTIONS, caller, tag)
+ : createRequest(Request.OPTIONS, caller, callee, tag);
ClientTransaction clientTransaction =
mSipProvider.getNewClientTransaction(request);
clientTransaction.sendRequest();
return clientTransaction;
} catch (Exception e) {
- throw new SipException("sendKeepAlive()", e);
+ throw new SipException("sendOptions()", e);
}
}
@@ -249,23 +265,29 @@
return ct;
}
+ private Request createRequest(String requestType, SipProfile caller,
+ SipProfile callee, String tag) throws ParseException, SipException {
+ FromHeader fromHeader = createFromHeader(caller, tag);
+ ToHeader toHeader = createToHeader(callee);
+ SipURI requestURI = callee.getUri();
+ List<ViaHeader> viaHeaders = createViaHeaders();
+ CallIdHeader callIdHeader = createCallIdHeader();
+ CSeqHeader cSeqHeader = createCSeqHeader(requestType);
+ MaxForwardsHeader maxForwards = createMaxForwardsHeader();
+
+ Request request = mMessageFactory.createRequest(requestURI,
+ requestType, callIdHeader, cSeqHeader, fromHeader,
+ toHeader, viaHeaders, maxForwards);
+
+ request.addHeader(createContactHeader(caller));
+ return request;
+ }
+
public ClientTransaction sendInvite(SipProfile caller, SipProfile callee,
String sessionDescription, String tag)
throws SipException {
try {
- FromHeader fromHeader = createFromHeader(caller, tag);
- ToHeader toHeader = createToHeader(callee);
- SipURI requestURI = callee.getUri();
- List<ViaHeader> viaHeaders = createViaHeaders();
- CallIdHeader callIdHeader = createCallIdHeader();
- CSeqHeader cSeqHeader = createCSeqHeader(Request.INVITE);
- MaxForwardsHeader maxForwards = createMaxForwardsHeader();
-
- Request request = mMessageFactory.createRequest(requestURI,
- Request.INVITE, callIdHeader, cSeqHeader, fromHeader,
- toHeader, viaHeaders, maxForwards);
-
- request.addHeader(createContactHeader(caller));
+ Request request = createRequest(Request.INVITE, caller, callee, tag);
request.setContent(sessionDescription,
mHeaderFactory.createContentTypeHeader(
"application", "sdp"));
@@ -305,7 +327,7 @@
}
}
- private ServerTransaction getServerTransaction(RequestEvent event)
+ public ServerTransaction getServerTransaction(RequestEvent event)
throws SipException {
ServerTransaction transaction = event.getServerTransaction();
if (transaction == null) {
@@ -344,13 +366,14 @@
*/
public ServerTransaction sendInviteOk(RequestEvent event,
SipProfile localProfile, String sessionDescription,
- ServerTransaction inviteTransaction)
- throws SipException {
+ ServerTransaction inviteTransaction, String externalIp,
+ int externalPort) throws SipException {
try {
Request request = event.getRequest();
Response response = mMessageFactory.createResponse(Response.OK,
request);
- response.addHeader(createContactHeader(localProfile));
+ response.addHeader(createContactHeader(localProfile, externalIp,
+ externalPort));
response.setContent(sessionDescription,
mHeaderFactory.createContentTypeHeader(
"application", "sdp"));
@@ -419,9 +442,13 @@
public void sendResponse(RequestEvent event, int responseCode)
throws SipException {
try {
+ Request request = event.getRequest();
Response response = mMessageFactory.createResponse(
- responseCode, event.getRequest());
- if (DEBUG) Log.d(TAG, "send response: " + response);
+ responseCode, request);
+ if (DEBUG && (!Request.OPTIONS.equals(request.getMethod())
+ || DEBUG_PING)) {
+ Log.d(TAG, "send response: " + response);
+ }
getServerTransaction(event).sendResponse(response);
} catch (ParseException e) {
throw new SipException("sendResponse()", e);
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 5ad5d26..47863bd 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -69,10 +69,11 @@
public final class SipService extends ISipService.Stub {
static final String TAG = "SipService";
static final boolean DEBUGV = false;
- static final boolean DEBUG = false;
+ static final boolean DEBUG = true;
private static final int EXPIRY_TIME = 3600;
private static final int SHORT_EXPIRY_TIME = 10;
private static final int MIN_EXPIRY_TIME = 60;
+ private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds
private Context mContext;
private String mLocalIp;
@@ -378,7 +379,7 @@
private void grabWifiLock() {
if (mWifiLock == null) {
- if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ acquire wifi lock");
+ if (DEBUG) Log.d(TAG, "acquire wifi lock");
mWifiLock = ((WifiManager)
mContext.getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
@@ -389,7 +390,7 @@
private void releaseWifiLock() {
if (mWifiLock != null) {
- if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ release wifi lock");
+ if (DEBUG) Log.d(TAG, "release wifi lock");
mWifiLock.release();
mWifiLock = null;
stopWifiScanner();
@@ -459,9 +460,30 @@
}
}
- private void startPortMappingLifetimeMeasurement(SipSessionGroup group) {
- mIntervalMeasurementProcess = new IntervalMeasurementProcess(group);
- mIntervalMeasurementProcess.start();
+ private void startPortMappingLifetimeMeasurement(
+ SipProfile localProfile) {
+ startPortMappingLifetimeMeasurement(localProfile, -1);
+ }
+
+ private void startPortMappingLifetimeMeasurement(
+ SipProfile localProfile, int maxInterval) {
+ if ((mIntervalMeasurementProcess == null)
+ && (mKeepAliveInterval == -1)
+ && isBehindNAT(mLocalIp)) {
+ Log.d(TAG, "start NAT port mapping timeout measurement on "
+ + localProfile.getUriString());
+
+ mIntervalMeasurementProcess =
+ new IntervalMeasurementProcess(localProfile, maxInterval);
+ mIntervalMeasurementProcess.start();
+ }
+ }
+
+ private void restartPortMappingLifetimeMeasurement(
+ SipProfile localProfile, int maxInterval) {
+ stopPortMappingMeasurement();
+ mKeepAliveInterval = -1;
+ startPortMappingLifetimeMeasurement(localProfile, maxInterval);
}
private synchronized void addPendingSession(ISipSession session) {
@@ -500,6 +522,33 @@
return false;
}
+ private synchronized void onKeepAliveIntervalChanged() {
+ for (SipSessionGroupExt group : mSipGroups.values()) {
+ group.onKeepAliveIntervalChanged();
+ }
+ }
+
+ private int getKeepAliveInterval() {
+ return (mKeepAliveInterval < 0)
+ ? DEFAULT_KEEPALIVE_INTERVAL
+ : mKeepAliveInterval;
+ }
+
+ private boolean isBehindNAT(String address) {
+ try {
+ byte[] d = InetAddress.getByName(address).getAddress();
+ if ((d[0] == 10) ||
+ (((0x000000FF & ((int)d[0])) == 172) &&
+ ((0x000000F0 & ((int)d[1])) == 16)) ||
+ (((0x000000FF & ((int)d[0])) == 192) &&
+ ((0x000000FF & ((int)d[1])) == 168))) {
+ return true;
+ }
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "isBehindAT()" + address, e);
+ }
+ return false;
+ }
private class SipSessionGroupExt extends SipSessionAdapter {
private SipSessionGroup mSipGroup;
@@ -527,6 +576,16 @@
return mSipGroup.containsSession(callId);
}
+ public void onKeepAliveIntervalChanged() {
+ mAutoRegistration.onKeepAliveIntervalChanged();
+ }
+
+ // TODO: remove this method once SipWakeupTimer can better handle variety
+ // of timeout values
+ void setWakeupTimer(SipWakeupTimer timer) {
+ mSipGroup.setWakeupTimer(timer);
+ }
+
// network connectivity is tricky because network can be disconnected
// at any instant so need to deal with exceptions carefully even when
// you think you are connected
@@ -534,7 +593,7 @@
SipProfile localProfile, String password) throws SipException {
try {
return new SipSessionGroup(localIp, localProfile, password,
- mMyWakeLock);
+ mTimer, mMyWakeLock);
} catch (IOException e) {
// network disconnected
Log.w(TAG, "createSipSessionGroup(): network disconnected?");
@@ -697,158 +756,153 @@
}
}
- private class IntervalMeasurementProcess extends SipSessionAdapter
- implements Runnable {
- private static final String TAG = "\\INTERVAL/";
- private static final int MAX_INTERVAL = 120; // seconds
- private static final int MIN_INTERVAL = SHORT_EXPIRY_TIME;
- private static final int PASS_THRESHOLD = 6;
+ private class IntervalMeasurementProcess implements Runnable,
+ SipSessionGroup.KeepAliveProcessCallback {
+ private static final String TAG = "SipKeepAliveInterval";
+ private static final int MAX_INTERVAL = 120; // in seconds
+ private static final int MIN_INTERVAL = 5; // in seconds
+ private static final int PASS_THRESHOLD = 10;
+ private static final int MAX_RETRY_COUNT = 5;
+ private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds
private SipSessionGroupExt mGroup;
private SipSessionGroup.SipSessionImpl mSession;
- private boolean mRunning;
- private int mMinInterval = 10;
- private int mMaxInterval = MAX_INTERVAL;
- private int mInterval = MAX_INTERVAL / 2;
- private int mPassCounter = 0;
- private SipWakeupTimer mTimer = new SipWakeupTimer(mContext, mExecutor);
- // TODO: fix SipWakeupTimer so that we only use one instance of the timer
+ private int mMinInterval = DEFAULT_KEEPALIVE_INTERVAL; // in seconds
+ private int mMaxInterval;
+ private int mInterval;
+ private int mPassCount = 0;
- public IntervalMeasurementProcess(SipSessionGroup group) {
+ public IntervalMeasurementProcess(SipProfile localProfile, int maxInterval) {
+ mMaxInterval = (maxInterval < 0) ? MAX_INTERVAL : maxInterval;
+ mInterval = (mMaxInterval + mMinInterval) / 2;
+
+ // Don't start measurement if the interval is too small
+ if (mInterval < MIN_INTERVAL) {
+ Log.w(TAG, "interval is too small; measurement aborted; "
+ + "maxInterval=" + mMaxInterval);
+ return;
+ }
+
try {
- mGroup = new SipSessionGroupExt(
- group.getLocalProfile(), null, null);
- mSession = (SipSessionGroup.SipSessionImpl)
- mGroup.createSession(this);
+ mGroup = new SipSessionGroupExt(localProfile, null, null);
+ // TODO: remove this line once SipWakeupTimer can better handle
+ // variety of timeout values
+ mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor));
} catch (Exception e) {
Log.w(TAG, "start interval measurement error: " + e);
}
}
public void start() {
- if (mRunning) return;
- mRunning = true;
- mTimer.set(mInterval * 1000, this);
- if (DEBUGV) Log.v(TAG, "start interval measurement");
- run();
+ synchronized (SipService.this) {
+ Log.d(TAG, "start measurement w interval=" + mInterval);
+ if (mSession == null) {
+ mSession = (SipSessionGroup.SipSessionImpl)
+ mGroup.createSession(null);
+ }
+ try {
+ mSession.startKeepAliveProcess(mInterval, this);
+ } catch (SipException e) {
+ Log.e(TAG, "start()", e);
+ }
+ }
}
public void stop() {
- mRunning = false;
- mTimer.cancel(this);
+ synchronized (SipService.this) {
+ if (mSession != null) {
+ mSession.stopKeepAliveProcess();
+ mSession = null;
+ }
+ mTimer.cancel(this);
+ }
}
private void restart() {
- mTimer.cancel(this);
- mTimer.set(mInterval * 1000, this);
- }
-
- private void calculateNewInterval() {
- if (!mSession.isReRegisterRequired()) {
- if (++mPassCounter != PASS_THRESHOLD) return;
- // update the interval, since the current interval is good to
- // keep the port mapping.
- mKeepAliveInterval = mMinInterval = mInterval;
- } else {
- // Since the rport is changed, shorten the interval.
- mSession.clearReRegisterRequired();
- mMaxInterval = mInterval;
- }
- if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) {
- // update mKeepAliveInterval and stop measurement.
- stop();
- mKeepAliveInterval = mMinInterval;
- if (DEBUGV) Log.v(TAG, "measured interval: " + mKeepAliveInterval);
- } else {
- // calculate the new interval and continue.
- mInterval = (mMaxInterval + mMinInterval) / 2;
- mPassCounter = 0;
- if (DEBUGV) {
- Log.v(TAG, " current interval: " + mKeepAliveInterval
- + "test new interval: " + mInterval);
- }
- restart();
- }
- }
-
- public void run() {
synchronized (SipService.this) {
- if (!mRunning) return;
+ // Return immediately if the measurement process is stopped
+ if (mSession == null) return;
+
+ Log.d(TAG, "restart measurement w interval=" + mInterval);
try {
- mSession.sendKeepAlive();
- calculateNewInterval();
- } catch (Throwable t) {
- stop();
- Log.w(TAG, "interval measurement error: " + t);
+ mSession.stopKeepAliveProcess();
+ mPassCount = 0;
+ mSession.startKeepAliveProcess(mInterval, this);
+ } catch (SipException e) {
+ Log.e(TAG, "restart()", e);
}
}
}
- }
- // KeepAliveProcess is controlled by AutoRegistrationProcess.
- // All methods will be invoked in sync with SipService.this.
- private class KeepAliveProcess implements Runnable {
- private static final String TAG = "\\KEEPALIVE/";
- private static final int INTERVAL = 10;
- private SipSessionGroup.SipSessionImpl mSession;
- private boolean mRunning = false;
- private int mInterval = INTERVAL;
-
- public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) {
- mSession = session;
+ // SipSessionGroup.KeepAliveProcessCallback
+ @Override
+ public void onResponse(boolean portChanged) {
+ synchronized (SipService.this) {
+ if (!portChanged) {
+ if (++mPassCount != PASS_THRESHOLD) return;
+ // update the interval, since the current interval is good to
+ // keep the port mapping.
+ mKeepAliveInterval = mMinInterval = mInterval;
+ if (DEBUG) {
+ Log.d(TAG, "measured good keepalive interval: "
+ + mKeepAliveInterval);
+ }
+ onKeepAliveIntervalChanged();
+ } else {
+ // Since the rport is changed, shorten the interval.
+ mMaxInterval = mInterval;
+ }
+ if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) {
+ // update mKeepAliveInterval and stop measurement.
+ stop();
+ mKeepAliveInterval = mMinInterval;
+ if (DEBUG) {
+ Log.d(TAG, "measured keepalive interval: "
+ + mKeepAliveInterval);
+ }
+ } else {
+ // calculate the new interval and continue.
+ mInterval = (mMaxInterval + mMinInterval) / 2;
+ if (DEBUG) {
+ Log.d(TAG, "current interval: " + mKeepAliveInterval
+ + ", test new interval: " + mInterval);
+ }
+ restart();
+ }
+ }
}
- public void start() {
- if (mRunning) return;
- mRunning = true;
- mTimer.set(INTERVAL * 1000, this);
- }
-
- private void restart(int duration) {
- if (DEBUG) Log.d(TAG, "Refresh NAT port mapping " + duration + "s later.");
- mTimer.cancel(this);
- mTimer.set(duration * 1000, this);
+ // SipSessionGroup.KeepAliveProcessCallback
+ @Override
+ public void onError(int errorCode, String description) {
+ Log.w(TAG, "interval measurement error: " + description);
+ restartLater();
}
// timeout handler
+ @Override
public void run() {
- synchronized (SipService.this) {
- if (!mRunning) return;
-
- if (DEBUGV) Log.v(TAG, "~~~ keepalive: "
- + mSession.getLocalProfile().getUriString());
- SipSessionGroup.SipSessionImpl session = mSession.duplicate();
- try {
- session.sendKeepAlive();
- if (session.isReRegisterRequired()) {
- // Acquire wake lock for the registration process. The
- // lock will be released when registration is complete.
- mMyWakeLock.acquire(mSession);
- mSession.register(EXPIRY_TIME);
- }
- if (mKeepAliveInterval > mInterval) {
- mInterval = mKeepAliveInterval;
- restart(mInterval);
- }
- } catch (Throwable t) {
- Log.w(TAG, "keepalive error: " + t);
- }
- }
+ mTimer.cancel(this);
+ restart();
}
- public void stop() {
- if (DEBUGV && (mSession != null)) Log.v(TAG, "stop keepalive:"
- + mSession.getLocalProfile().getUriString());
- mRunning = false;
- mSession = null;
- mTimer.cancel(this);
+ private void restartLater() {
+ synchronized (SipService.this) {
+ int interval = NAT_MEASUREMENT_RETRY_INTERVAL;
+ Log.d(TAG, "Retry measurement " + interval + "s later.");
+ mTimer.cancel(this);
+ mTimer.set(interval * 1000, this);
+ }
}
}
private class AutoRegistrationProcess extends SipSessionAdapter
- implements Runnable {
+ implements Runnable, SipSessionGroup.KeepAliveProcessCallback {
+ private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10;
+ private String TAG = "SipAudoReg";
+
private SipSessionGroup.SipSessionImpl mSession;
+ private SipSessionGroup.SipSessionImpl mKeepAliveSession;
private SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
- private KeepAliveProcess mKeepAliveProcess;
private int mBackoff = 1;
private boolean mRegistered;
private long mExpiryTime;
@@ -856,6 +910,8 @@
private String mErrorMessage;
private boolean mRunning = false;
+ private int mKeepAliveSuccessCount = 0;
+
private String getAction() {
return toString();
}
@@ -869,27 +925,89 @@
// return right away if no active network connection.
if (mSession == null) return;
- synchronized (SipService.this) {
- if (isBehindNAT(mLocalIp)
- && (mIntervalMeasurementProcess == null)
- && (mKeepAliveInterval == -1)) {
- // Start keep-alive interval measurement, here we allow
- // the first profile only as the target service provider
- // to measure the life time of NAT port mapping.
- startPortMappingLifetimeMeasurement(group);
- }
- }
-
// start unregistration to clear up old registration at server
// TODO: when rfc5626 is deployed, use reg-id and sip.instance
// in registration to avoid adding duplicate entries to server
mMyWakeLock.acquire(mSession);
mSession.unregister();
- if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for "
- + mSession.getLocalProfile().getUriString());
+ if (DEBUG) TAG = mSession.getLocalProfile().getUriString();
+ if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess");
}
}
+ private void startKeepAliveProcess(int interval) {
+ Log.d(TAG, "start keepalive w interval=" + interval);
+ if (mKeepAliveSession == null) {
+ mKeepAliveSession = mSession.duplicate();
+ } else {
+ mKeepAliveSession.stopKeepAliveProcess();
+ }
+ try {
+ mKeepAliveSession.startKeepAliveProcess(interval, this);
+ } catch (SipException e) {
+ Log.e(TAG, "failed to start keepalive w interval=" + interval,
+ e);
+ }
+ }
+
+ private void stopKeepAliveProcess() {
+ if (mKeepAliveSession != null) {
+ mKeepAliveSession.stopKeepAliveProcess();
+ mKeepAliveSession = null;
+ }
+ mKeepAliveSuccessCount = 0;
+ }
+
+ // SipSessionGroup.KeepAliveProcessCallback
+ @Override
+ public void onResponse(boolean portChanged) {
+ synchronized (SipService.this) {
+ if (portChanged) {
+ int interval = getKeepAliveInterval();
+ if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) {
+ Log.i(TAG, "keepalive doesn't work with interval "
+ + interval + ", past success count="
+ + mKeepAliveSuccessCount);
+ if (interval > DEFAULT_KEEPALIVE_INTERVAL) {
+ restartPortMappingLifetimeMeasurement(
+ mSession.getLocalProfile(), interval);
+ mKeepAliveSuccessCount = 0;
+ }
+ } else {
+ Log.i(TAG, "keep keepalive going with interval "
+ + interval + ", past success count="
+ + mKeepAliveSuccessCount);
+ mKeepAliveSuccessCount /= 2;
+ }
+ } else {
+ // Start keep-alive interval measurement on the first
+ // successfully kept-alive SipSessionGroup
+ startPortMappingLifetimeMeasurement(
+ mSession.getLocalProfile());
+ mKeepAliveSuccessCount++;
+ }
+
+ if (!mRunning || !portChanged) return;
+
+ // The keep alive process is stopped when port is changed;
+ // Nullify the session so that the process can be restarted
+ // again when the re-registration is done
+ mKeepAliveSession = null;
+
+ // Acquire wake lock for the registration process. The
+ // lock will be released when registration is complete.
+ mMyWakeLock.acquire(mSession);
+ mSession.register(EXPIRY_TIME);
+ }
+ }
+
+ // SipSessionGroup.KeepAliveProcessCallback
+ @Override
+ public void onError(int errorCode, String description) {
+ Log.e(TAG, "keepalive error: " + description);
+ onResponse(true); // re-register immediately
+ }
+
public void stop() {
if (!mRunning) return;
mRunning = false;
@@ -900,15 +1018,23 @@
}
mTimer.cancel(this);
- if (mKeepAliveProcess != null) {
- mKeepAliveProcess.stop();
- mKeepAliveProcess = null;
- }
+ stopKeepAliveProcess();
mRegistered = false;
setListener(mProxy.getListener());
}
+ public void onKeepAliveIntervalChanged() {
+ if (mKeepAliveSession != null) {
+ int newInterval = getKeepAliveInterval();
+ if (DEBUGV) {
+ Log.v(TAG, "restart keepalive w interval=" + newInterval);
+ }
+ mKeepAliveSuccessCount = 0;
+ startKeepAliveProcess(newInterval);
+ }
+ }
+
public void setListener(ISipSessionListener listener) {
synchronized (SipService.this) {
mProxy.setListener(listener);
@@ -955,13 +1081,14 @@
}
// timeout handler: re-register
+ @Override
public void run() {
synchronized (SipService.this) {
if (!mRunning) return;
mErrorCode = SipErrorCode.NO_ERROR;
mErrorMessage = null;
- if (DEBUG) Log.d(TAG, "~~~ registering");
+ if (DEBUG) Log.d(TAG, "registering");
if (mConnected) {
mMyWakeLock.acquire(mSession);
mSession.register(EXPIRY_TIME);
@@ -969,22 +1096,6 @@
}
}
- private boolean isBehindNAT(String address) {
- try {
- byte[] d = InetAddress.getByName(address).getAddress();
- if ((d[0] == 10) ||
- (((0x000000FF & ((int)d[0])) == 172) &&
- ((0x000000F0 & ((int)d[1])) == 16)) ||
- (((0x000000FF & ((int)d[0])) == 192) &&
- ((0x000000FF & ((int)d[1])) == 168))) {
- return true;
- }
- } catch (UnknownHostException e) {
- Log.e(TAG, "isBehindAT()" + address, e);
- }
- return false;
- }
-
private void restart(int duration) {
if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later.");
mTimer.cancel(this);
@@ -1030,7 +1141,6 @@
mProxy.onRegistrationDone(session, duration);
if (duration > 0) {
- mSession.clearReRegisterRequired();
mExpiryTime = SystemClock.elapsedRealtime()
+ (duration * 1000);
@@ -1043,13 +1153,10 @@
}
restart(duration);
- if (isBehindNAT(mLocalIp) ||
- mSession.getLocalProfile().getSendKeepAlive()) {
- if (mKeepAliveProcess == null) {
- mKeepAliveProcess =
- new KeepAliveProcess(mSession);
- }
- mKeepAliveProcess.start();
+ SipProfile localProfile = mSession.getLocalProfile();
+ if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp)
+ || localProfile.getSendKeepAlive())) {
+ startKeepAliveProcess(getKeepAliveInterval());
}
}
mMyWakeLock.release(session);
@@ -1103,10 +1210,6 @@
private void restartLater() {
mRegistered = false;
restart(backoffDuration());
- if (mKeepAliveProcess != null) {
- mKeepAliveProcess.stop();
- mKeepAliveProcess = null;
- }
}
}
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 4837eb9..047eb8d 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -21,6 +21,8 @@
import gov.nist.javax.sip.header.SIPHeaderNames;
import gov.nist.javax.sip.header.ProxyAuthenticate;
import gov.nist.javax.sip.header.WWWAuthenticate;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
import gov.nist.javax.sip.message.SIPMessage;
import android.net.sip.ISipSession;
@@ -28,6 +30,7 @@
import android.net.sip.SipErrorCode;
import android.net.sip.SipProfile;
import android.net.sip.SipSession;
+import android.net.sip.SipSessionAdapter;
import android.text.TextUtils;
import android.util.Log;
@@ -89,6 +92,8 @@
private static final String THREAD_POOL_SIZE = "1";
private static final int EXPIRY_TIME = 3600; // in seconds
private static final int CANCEL_CALL_TIMER = 3; // in seconds
+ private static final int KEEPALIVE_TIMEOUT = 3; // in seconds
+ private static final int INCALL_KEEPALIVE_INTERVAL = 10; // in seconds
private static final long WAKE_LOCK_HOLDING_TIME = 500; // in milliseconds
private static final EventObject DEREGISTER = new EventObject("Deregister");
@@ -107,25 +112,38 @@
private SipSessionImpl mCallReceiverSession;
private String mLocalIp;
+ private SipWakeupTimer mWakeupTimer;
private SipWakeLock mWakeLock;
// call-id-to-SipSession map
private Map<String, SipSessionImpl> mSessionMap =
new HashMap<String, SipSessionImpl>();
+ // external address observed from any response
+ private String mExternalIp;
+ private int mExternalPort;
+
/**
* @param myself the local profile with password crossed out
* @param password the password of the profile
* @throws IOException if cannot assign requested address
*/
public SipSessionGroup(String localIp, SipProfile myself, String password,
- SipWakeLock wakeLock) throws SipException, IOException {
+ SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException,
+ IOException {
mLocalProfile = myself;
mPassword = password;
+ mWakeupTimer = timer;
mWakeLock = wakeLock;
reset(localIp);
}
+ // TODO: remove this method once SipWakeupTimer can better handle variety
+ // of timeout values
+ void setWakeupTimer(SipWakeupTimer timer) {
+ mWakeupTimer = timer;
+ }
+
synchronized void reset(String localIp) throws SipException, IOException {
mLocalIp = localIp;
if (localIp == null) return;
@@ -161,6 +179,8 @@
mCallReceiverSession = null;
mSessionMap.clear();
+
+ resetExternalAddress();
}
synchronized void onConnectivityChanged() {
@@ -176,6 +196,12 @@
}
}
+ synchronized void resetExternalAddress() {
+ Log.d(TAG, " reset external addr on " + mSipStack);
+ mExternalIp = null;
+ mExternalPort = 0;
+ }
+
public SipProfile getLocalProfile() {
return mLocalProfile;
}
@@ -349,29 +375,105 @@
return null;
}
+ private void extractExternalAddress(ResponseEvent evt) {
+ Response response = evt.getResponse();
+ ViaHeader viaHeader = (ViaHeader)(response.getHeader(
+ SIPHeaderNames.VIA));
+ if (viaHeader == null) return;
+ int rport = viaHeader.getRPort();
+ String externalIp = viaHeader.getReceived();
+ if ((rport > 0) && (externalIp != null)) {
+ mExternalIp = externalIp;
+ mExternalPort = rport;
+ Log.d(TAG, " got external addr " + externalIp + ":" + rport
+ + " on " + mSipStack);
+ }
+ }
+
private class SipSessionCallReceiverImpl extends SipSessionImpl {
public SipSessionCallReceiverImpl(ISipSessionListener listener) {
super(listener);
}
+ private SipSessionImpl createNewSession(RequestEvent event,
+ ISipSessionListener listener, ServerTransaction transaction)
+ throws SipException {
+ SipSessionImpl newSession = new SipSessionImpl(listener);
+ newSession.mServerTransaction = transaction;
+ newSession.mState = SipSession.State.INCOMING_CALL;
+ newSession.mDialog = newSession.mServerTransaction.getDialog();
+ newSession.mInviteReceived = event;
+ newSession.mPeerProfile = createPeerProfile(event.getRequest());
+ newSession.mPeerSessionDescription =
+ extractContent(event.getRequest());
+ return newSession;
+ }
+
+ private int processInviteWithReplaces(RequestEvent event,
+ ReplacesHeader replaces) {
+ String callId = replaces.getCallId();
+ SipSessionImpl session = mSessionMap.get(callId);
+ if (session == null) {
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+
+ Dialog dialog = session.mDialog;
+ if (dialog == null) return Response.DECLINE;
+
+ if (!dialog.getLocalTag().equals(replaces.getToTag()) ||
+ !dialog.getRemoteTag().equals(replaces.getFromTag())) {
+ // No match is found, returns 481.
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+
+ ReferredByHeader referredBy = (ReferredByHeader) event.getRequest()
+ .getHeader(ReferredByHeader.NAME);
+ if ((referredBy == null) ||
+ !dialog.getRemoteParty().equals(referredBy.getAddress())) {
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+ return Response.OK;
+ }
+
+ private void processNewInviteRequest(RequestEvent event)
+ throws SipException {
+ ReplacesHeader replaces = (ReplacesHeader) event.getRequest()
+ .getHeader(ReplacesHeader.NAME);
+ SipSessionImpl newSession = null;
+ if (replaces != null) {
+ int response = processInviteWithReplaces(event, replaces);
+ if (DEBUG) {
+ Log.v(TAG, "ReplacesHeader: " + replaces
+ + " response=" + response);
+ }
+ if (response == Response.OK) {
+ SipSessionImpl replacedSession =
+ mSessionMap.get(replaces.getCallId());
+ // got INVITE w/ replaces request.
+ newSession = createNewSession(event,
+ replacedSession.mProxy.getListener(),
+ mSipHelper.getServerTransaction(event));
+ newSession.mProxy.onCallTransferring(newSession,
+ newSession.mPeerSessionDescription);
+ } else {
+ mSipHelper.sendResponse(event, response);
+ }
+ } else {
+ // New Incoming call.
+ newSession = createNewSession(event, mProxy,
+ mSipHelper.sendRinging(event, generateTag()));
+ mProxy.onRinging(newSession, newSession.mPeerProfile,
+ newSession.mPeerSessionDescription);
+ }
+ if (newSession != null) addSipSession(newSession);
+ }
+
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
+ SipSession.State.toString(mState) + ": processing "
+ log(evt));
if (isRequestEvent(Request.INVITE, evt)) {
- RequestEvent event = (RequestEvent) evt;
- SipSessionImpl newSession = new SipSessionImpl(mProxy);
- newSession.mState = SipSession.State.INCOMING_CALL;
- newSession.mServerTransaction = mSipHelper.sendRinging(event,
- generateTag());
- newSession.mDialog = newSession.mServerTransaction.getDialog();
- newSession.mInviteReceived = event;
- newSession.mPeerProfile = createPeerProfile(event.getRequest());
- newSession.mPeerSessionDescription =
- extractContent(event.getRequest());
- addSipSession(newSession);
- mProxy.onRinging(newSession, newSession.mPeerProfile,
- newSession.mPeerSessionDescription);
+ processNewInviteRequest((RequestEvent) evt);
return true;
} else if (isRequestEvent(Request.OPTIONS, evt)) {
mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
@@ -382,6 +484,12 @@
}
}
+ static interface KeepAliveProcessCallback {
+ /** Invoked when the response of keeping alive comes back. */
+ void onResponse(boolean portChanged);
+ void onError(int errorCode, String description);
+ }
+
class SipSessionImpl extends ISipSession.Stub {
SipProfile mPeerProfile;
SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
@@ -392,12 +500,12 @@
ClientTransaction mClientTransaction;
String mPeerSessionDescription;
boolean mInCall;
- SessionTimer mTimer;
+ SessionTimer mSessionTimer;
int mAuthenticationRetryCount;
- // for registration
- boolean mReRegisterFlag = false;
- int mRPort = 0;
+ private KeepAliveProcess mKeepAliveProcess;
+
+ private SipSessionImpl mKeepAliveSession;
// lightweight timer
class SessionTimer {
@@ -467,6 +575,11 @@
mClientTransaction = null;
cancelSessionTimer();
+
+ if (mKeepAliveSession != null) {
+ mKeepAliveSession.stopKeepAliveProcess();
+ mKeepAliveSession = null;
+ }
}
public boolean isInCall() {
@@ -512,7 +625,9 @@
try {
processCommand(command);
} catch (Throwable e) {
- Log.w(TAG, "command error: " + command, e);
+ Log.w(TAG, "command error: " + command + ": "
+ + mLocalProfile.getUriString(),
+ getRootCause(e));
onError(e);
}
}
@@ -553,34 +668,6 @@
doCommandAsync(DEREGISTER);
}
- public boolean isReRegisterRequired() {
- return mReRegisterFlag;
- }
-
- public void clearReRegisterRequired() {
- mReRegisterFlag = false;
- }
-
- public void sendKeepAlive() {
- mState = SipSession.State.PINGING;
- try {
- processCommand(new OptionsCommand());
- for (int i = 0; i < 15; i++) {
- if (SipSession.State.PINGING != mState) break;
- Thread.sleep(200);
- }
- if (SipSession.State.PINGING == mState) {
- // FIXME: what to do if server doesn't respond
- reset();
- if (DEBUG) Log.w(TAG, "no response from ping");
- }
- } catch (SipException e) {
- Log.e(TAG, "sendKeepAlive failed", e);
- } catch (InterruptedException e) {
- Log.e(TAG, "sendKeepAlive interrupted", e);
- }
- }
-
private void processCommand(EventObject command) throws SipException {
if (isLoggable(command)) Log.d(TAG, "process cmd: " + command);
if (!process(command)) {
@@ -612,11 +699,17 @@
synchronized (SipSessionGroup.this) {
if (isClosed()) return false;
+ if (mKeepAliveProcess != null) {
+ // event consumed by keepalive process
+ if (mKeepAliveProcess.process(evt)) return true;
+ }
+
Dialog dialog = null;
if (evt instanceof RequestEvent) {
dialog = ((RequestEvent) evt).getDialog();
} else if (evt instanceof ResponseEvent) {
dialog = ((ResponseEvent) evt).getDialog();
+ extractExternalAddress((ResponseEvent) evt);
}
if (dialog != null) mDialog = dialog;
@@ -627,9 +720,6 @@
case SipSession.State.DEREGISTERING:
processed = registeringToReady(evt);
break;
- case SipSession.State.PINGING:
- processed = keepAliveProcess(evt);
- break;
case SipSession.State.READY_TO_CALL:
processed = readyForCall(evt);
break;
@@ -754,10 +844,6 @@
case SipSession.State.OUTGOING_CALL_CANCELING:
onError(SipErrorCode.TIME_OUT, event.toString());
break;
- case SipSession.State.PINGING:
- reset();
- mReRegisterFlag = true;
- break;
default:
Log.d(TAG, " do nothing");
@@ -778,48 +864,6 @@
return expires;
}
- private boolean keepAliveProcess(EventObject evt) throws SipException {
- if (evt instanceof OptionsCommand) {
- mClientTransaction = mSipHelper.sendKeepAlive(mLocalProfile,
- generateTag());
- mDialog = mClientTransaction.getDialog();
- addSipSession(this);
- return true;
- } else if (evt instanceof ResponseEvent) {
- return parseOptionsResult(evt);
- }
- return false;
- }
-
- private boolean parseOptionsResult(EventObject evt) {
- if (expectResponse(Request.OPTIONS, evt)) {
- ResponseEvent event = (ResponseEvent) evt;
- int rPort = getRPortFromResponse(event.getResponse());
- if (rPort != -1) {
- if (mRPort == 0) mRPort = rPort;
- if (mRPort != rPort) {
- mReRegisterFlag = true;
- if (DEBUG) Log.w(TAG, String.format(
- "rport is changed: %d <> %d", mRPort, rPort));
- mRPort = rPort;
- } else {
- if (DEBUG_PING) Log.w(TAG, "rport is the same: " + rPort);
- }
- } else {
- if (DEBUG) Log.w(TAG, "peer did not respond rport");
- }
- reset();
- return true;
- }
- return false;
- }
-
- private int getRPortFromResponse(Response response) {
- ViaHeader viaHeader = (ViaHeader)(response.getHeader(
- SIPHeaderNames.VIA));
- return (viaHeader == null) ? -1 : viaHeader.getRPort();
- }
-
private boolean registeringToReady(EventObject evt)
throws SipException {
if (expectResponse(Request.REGISTER, evt)) {
@@ -968,7 +1012,8 @@
mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived,
mLocalProfile,
((MakeCallCommand) evt).getSessionDescription(),
- mServerTransaction);
+ mServerTransaction,
+ mExternalIp, mExternalPort);
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
} else if (END_CALL == evt) {
@@ -991,7 +1036,13 @@
throws SipException {
// expect ACK, CANCEL request
if (isRequestEvent(Request.ACK, evt)) {
- establishCall();
+ String sdp = extractContent(((RequestEvent) evt).getRequest());
+ if (sdp != null) mPeerSessionDescription = sdp;
+ if (mPeerSessionDescription == null) {
+ onError(SipErrorCode.CLIENT_ERROR, "peer sdp is empty");
+ } else {
+ establishCall(false);
+ }
return true;
} else if (isRequestEvent(Request.CANCEL, evt)) {
// http://tools.ietf.org/html/rfc3261#section-9.2
@@ -1023,7 +1074,7 @@
case Response.OK:
mSipHelper.sendInviteAck(event, mDialog);
mPeerSessionDescription = extractContent(response);
- establishCall();
+ establishCall(true);
return true;
case Response.UNAUTHORIZED:
case Response.PROXY_AUTHENTICATION_REQUIRED:
@@ -1138,15 +1189,15 @@
// timeout in seconds
private void startSessionTimer(int timeout) {
if (timeout > 0) {
- mTimer = new SessionTimer();
- mTimer.start(timeout);
+ mSessionTimer = new SessionTimer();
+ mSessionTimer.start(timeout);
}
}
private void cancelSessionTimer() {
- if (mTimer != null) {
- mTimer.cancel();
- mTimer = null;
+ if (mSessionTimer != null) {
+ mSessionTimer.cancel();
+ mSessionTimer = null;
}
}
@@ -1155,10 +1206,26 @@
response.getStatusCode());
}
- private void establishCall() {
+ private void enableKeepAlive() {
+ if (mKeepAliveSession != null) {
+ mKeepAliveSession.stopKeepAliveProcess();
+ } else {
+ mKeepAliveSession = duplicate();
+ }
+ try {
+ mKeepAliveSession.startKeepAliveProcess(
+ INCALL_KEEPALIVE_INTERVAL, mPeerProfile, null);
+ } catch (SipException e) {
+ Log.w(TAG, "keepalive cannot be enabled; ignored", e);
+ mKeepAliveSession.stopKeepAliveProcess();
+ }
+ }
+
+ private void establishCall(boolean enableKeepAlive) {
mState = SipSession.State.IN_CALL;
mInCall = true;
cancelSessionTimer();
+ if (enableKeepAlive) enableKeepAlive();
mProxy.onCallEstablished(this, mPeerSessionDescription);
}
@@ -1272,6 +1339,174 @@
onRegistrationFailed(getErrorCode(statusCode),
createErrorMessage(response));
}
+
+ // Notes: SipSessionListener will be replaced by the keepalive process
+ // @param interval in seconds
+ public void startKeepAliveProcess(int interval,
+ KeepAliveProcessCallback callback) throws SipException {
+ synchronized (SipSessionGroup.this) {
+ startKeepAliveProcess(interval, mLocalProfile, callback);
+ }
+ }
+
+ // Notes: SipSessionListener will be replaced by the keepalive process
+ // @param interval in seconds
+ public void startKeepAliveProcess(int interval, SipProfile peerProfile,
+ KeepAliveProcessCallback callback) throws SipException {
+ synchronized (SipSessionGroup.this) {
+ if (mKeepAliveProcess != null) {
+ throw new SipException("Cannot create more than one "
+ + "keepalive process in a SipSession");
+ }
+ mPeerProfile = peerProfile;
+ mKeepAliveProcess = new KeepAliveProcess();
+ mProxy.setListener(mKeepAliveProcess);
+ mKeepAliveProcess.start(interval, callback);
+ }
+ }
+
+ public void stopKeepAliveProcess() {
+ synchronized (SipSessionGroup.this) {
+ if (mKeepAliveProcess != null) {
+ mKeepAliveProcess.stop();
+ mKeepAliveProcess = null;
+ }
+ }
+ }
+
+ class KeepAliveProcess extends SipSessionAdapter implements Runnable {
+ private static final String TAG = "SipKeepAlive";
+ private boolean mRunning = false;
+ private KeepAliveProcessCallback mCallback;
+
+ private boolean mPortChanged = false;
+ private int mRPort = 0;
+ private int mInterval; // just for debugging
+
+ // @param interval in seconds
+ void start(int interval, KeepAliveProcessCallback callback) {
+ if (mRunning) return;
+ mRunning = true;
+ mInterval = interval;
+ mCallback = new KeepAliveProcessCallbackProxy(callback);
+ mWakeupTimer.set(interval * 1000, this);
+ if (DEBUG) {
+ Log.d(TAG, "start keepalive:"
+ + mLocalProfile.getUriString());
+ }
+
+ // No need to run the first time in a separate thread for now
+ run();
+ }
+
+ // return true if the event is consumed
+ boolean process(EventObject evt) throws SipException {
+ if (mRunning && (mState == SipSession.State.PINGING)) {
+ if (evt instanceof ResponseEvent) {
+ if (parseOptionsResult(evt)) {
+ if (mPortChanged) {
+ resetExternalAddress();
+ stop();
+ } else {
+ cancelSessionTimer();
+ removeSipSession(SipSessionImpl.this);
+ }
+ mCallback.onResponse(mPortChanged);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // SipSessionAdapter
+ // To react to the session timeout event and network error.
+ @Override
+ public void onError(ISipSession session, int errorCode, String message) {
+ stop();
+ mCallback.onError(errorCode, message);
+ }
+
+ // SipWakeupTimer timeout handler
+ // To send out keepalive message.
+ @Override
+ public void run() {
+ synchronized (SipSessionGroup.this) {
+ if (!mRunning) return;
+
+ if (DEBUG_PING) {
+ String peerUri = (mPeerProfile == null)
+ ? "null"
+ : mPeerProfile.getUriString();
+ Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
+ + " --> " + peerUri + ", interval=" + mInterval);
+ }
+ try {
+ sendKeepAlive();
+ } catch (Throwable t) {
+ Log.w(TAG, "keepalive error: " + ": "
+ + mLocalProfile.getUriString(), getRootCause(t));
+ // It's possible that the keepalive process is being stopped
+ // during session.sendKeepAlive() so need to check mRunning
+ // again here.
+ if (mRunning) SipSessionImpl.this.onError(t);
+ }
+ }
+ }
+
+ void stop() {
+ synchronized (SipSessionGroup.this) {
+ if (DEBUG) {
+ Log.d(TAG, "stop keepalive:" + mLocalProfile.getUriString()
+ + ",RPort=" + mRPort);
+ }
+ mRunning = false;
+ mWakeupTimer.cancel(this);
+ reset();
+ }
+ }
+
+ private void sendKeepAlive() throws SipException, InterruptedException {
+ synchronized (SipSessionGroup.this) {
+ mState = SipSession.State.PINGING;
+ mClientTransaction = mSipHelper.sendOptions(
+ mLocalProfile, mPeerProfile, generateTag());
+ mDialog = mClientTransaction.getDialog();
+ addSipSession(SipSessionImpl.this);
+
+ startSessionTimer(KEEPALIVE_TIMEOUT);
+ // when timed out, onError() will be called with SipErrorCode.TIME_OUT
+ }
+ }
+
+ private boolean parseOptionsResult(EventObject evt) {
+ if (expectResponse(Request.OPTIONS, evt)) {
+ ResponseEvent event = (ResponseEvent) evt;
+ int rPort = getRPortFromResponse(event.getResponse());
+ if (rPort != -1) {
+ if (mRPort == 0) mRPort = rPort;
+ if (mRPort != rPort) {
+ mPortChanged = true;
+ if (DEBUG) Log.d(TAG, String.format(
+ "rport is changed: %d <> %d", mRPort, rPort));
+ mRPort = rPort;
+ } else {
+ if (DEBUG) Log.d(TAG, "rport is the same: " + rPort);
+ }
+ } else {
+ if (DEBUG) Log.w(TAG, "peer did not respond rport");
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private int getRPortFromResponse(Response response) {
+ ViaHeader viaHeader = (ViaHeader)(response.getHeader(
+ SIPHeaderNames.VIA));
+ return (viaHeader == null) ? -1 : viaHeader.getRPort();
+ }
+ }
}
/**
@@ -1363,15 +1598,16 @@
if (!isLoggable(s)) return false;
if (evt == null) return false;
- if (evt instanceof OptionsCommand) {
- return DEBUG_PING;
- } else if (evt instanceof ResponseEvent) {
+ if (evt instanceof ResponseEvent) {
Response response = ((ResponseEvent) evt).getResponse();
if (Request.OPTIONS.equals(response.getHeader(CSeqHeader.NAME))) {
return DEBUG_PING;
}
return DEBUG;
} else if (evt instanceof RequestEvent) {
+ if (isRequestEvent(Request.OPTIONS, evt)) {
+ return DEBUG_PING;
+ }
return DEBUG;
}
return false;
@@ -1387,12 +1623,6 @@
}
}
- private class OptionsCommand extends EventObject {
- public OptionsCommand() {
- super(SipSessionGroup.this);
- }
- }
-
private class RegisterCommand extends EventObject {
private int mDuration;
@@ -1434,4 +1664,46 @@
return mTimeout;
}
}
+
+ /** Class to help safely run KeepAliveProcessCallback in a different thread. */
+ static class KeepAliveProcessCallbackProxy implements KeepAliveProcessCallback {
+ private KeepAliveProcessCallback mCallback;
+
+ KeepAliveProcessCallbackProxy(KeepAliveProcessCallback callback) {
+ mCallback = callback;
+ }
+
+ private void proxy(Runnable runnable) {
+ // One thread for each calling back.
+ // Note: Guarantee ordering if the issue becomes important. Currently,
+ // the chance of handling two callback events at a time is none.
+ new Thread(runnable, "SIP-KeepAliveProcessCallbackThread").start();
+ }
+
+ public void onResponse(final boolean portChanged) {
+ if (mCallback == null) return;
+ proxy(new Runnable() {
+ public void run() {
+ try {
+ mCallback.onResponse(portChanged);
+ } catch (Throwable t) {
+ Log.w(TAG, "onResponse", t);
+ }
+ }
+ });
+ }
+
+ public void onError(final int errorCode, final String description) {
+ if (mCallback == null) return;
+ proxy(new Runnable() {
+ public void run() {
+ try {
+ mCallback.onError(errorCode, description);
+ } catch (Throwable t) {
+ Log.w(TAG, "onError", t);
+ }
+ }
+ });
+ }
+ }
}
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index f8be0a8..8655a3a 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -110,6 +110,20 @@
});
}
+ public void onCallTransferring(final ISipSession newSession,
+ final String sessionDescription) {
+ if (mListener == null) return;
+ proxy(new Runnable() {
+ public void run() {
+ try {
+ mListener.onCallTransferring(newSession, sessionDescription);
+ } catch (Throwable t) {
+ handle(t, "onCallTransferring()");
+ }
+ }
+ });
+ }
+
public void onCallBusy(final ISipSession session) {
if (mListener == null) return;
proxy(new Runnable() {
diff --git a/voip/java/com/android/server/sip/SipWakeupTimer.java b/voip/java/com/android/server/sip/SipWakeupTimer.java
index 9cc26b0..00d47ac 100644
--- a/voip/java/com/android/server/sip/SipWakeupTimer.java
+++ b/voip/java/com/android/server/sip/SipWakeupTimer.java
@@ -83,7 +83,7 @@
mEventQueue = null;
}
- private synchronized boolean stopped() {
+ private boolean stopped() {
if (mEventQueue == null) {
Log.w(TAG, "Timer stopped");
return true;
@@ -173,7 +173,7 @@
long triggerTime = event.mTriggerTime;
if (DEBUG_TIMER) {
- Log.d(TAG, " add event " + event + " scheduled at "
+ Log.d(TAG, " add event " + event + " scheduled on "
+ showTime(triggerTime) + " at " + showTime(now)
+ ", #events=" + mEventQueue.size());
printQueue();
@@ -233,7 +233,7 @@
}
@Override
- public void onReceive(Context context, Intent intent) {
+ public synchronized void onReceive(Context context, Intent intent) {
// This callback is already protected by AlarmManager's wake lock.
String action = intent.getAction();
if (getAction().equals(action)
@@ -261,16 +261,16 @@
}
}
- private synchronized void execute(long triggerTime) {
+ private void execute(long triggerTime) {
if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
+ showTime(triggerTime) + ": " + mEventQueue.size());
if (stopped() || mEventQueue.isEmpty()) return;
for (MyEvent event : mEventQueue) {
- if (event.mTriggerTime != triggerTime) break;
+ if (event.mTriggerTime != triggerTime) continue;
if (DEBUG_TIMER) Log.d(TAG, "execute " + event);
- event.mLastTriggerTime = event.mTriggerTime;
+ event.mLastTriggerTime = triggerTime;
event.mTriggerTime += event.mPeriod;
// run the callback in the handler thread to prevent deadlock
@@ -324,6 +324,8 @@
}
}
+ // Sort the events by mMaxPeriod so that the first event can be used to
+ // align events with larger periods
private static class MyEventComparator implements Comparator<MyEvent> {
public int compare(MyEvent e1, MyEvent e2) {
if (e1 == e2) return 0;
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 3c9a641..2a033d1 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1028,9 +1028,6 @@
boolean wifiTethered = false;
boolean wifiAvailable = false;
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
-
if (mCm == null) {
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
}
@@ -1043,14 +1040,14 @@
InterfaceConfiguration ifcg = null;
try {
- ifcg = service.getInterfaceConfig(intf);
+ ifcg = nwService.getInterfaceConfig(intf);
if (ifcg != null) {
/* IP/netmask: 192.168.43.1/255.255.255.0 */
ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
"192.168.43.1"), 24);
ifcg.interfaceFlags = "[up]";
- service.setInterfaceConfig(intf, ifcg);
+ nwService.setInterfaceConfig(intf, ifcg);
}
} catch (Exception e) {
Log.e(TAG, "Error configuring interface " + intf + ", :" + e);
@@ -1450,7 +1447,7 @@
* using the interface, stopping DHCP & disabling interface
*/
private void handleNetworkDisconnect() {
- Log.d(TAG, "Reset connections and stopping DHCP");
+ Log.d(TAG, "Stopping DHCP and clearing IP");
/*
* stop DHCP
@@ -1461,6 +1458,12 @@
mDhcpStateMachine = null;
}
+ try {
+ nwService.clearInterfaceAddresses(mInterfaceName);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to clear IP addresses on disconnect" + e);
+ }
+
/* Reset data structures */
mWifiInfo.setInetAddress(null);
mWifiInfo.setBSSID(null);
@@ -2656,13 +2659,11 @@
} else {
DhcpInfoInternal dhcpInfoInternal = WifiConfigStore.getIpConfiguration(
mLastNetworkId);
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- INetworkManagementService netd = INetworkManagementService.Stub.asInterface(b);
InterfaceConfiguration ifcg = new InterfaceConfiguration();
ifcg.addr = dhcpInfoInternal.makeLinkAddress();
ifcg.interfaceFlags = "[up]";
try {
- netd.setInterfaceConfig(mInterfaceName, ifcg);
+ nwService.setInterfaceConfig(mInterfaceName, ifcg);
Log.v(TAG, "Static IP configuration succeeded");
sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal);
} catch (RemoteException re) {