Merge "Part of fix for bug 5065047 build libchromium as a shared lib"
diff --git a/Android.mk b/Android.mk
index 7b8d0bc..5cb4d30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -93,6 +93,7 @@
core/java/android/bluetooth/IBluetoothHeadset.aidl \
core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
+ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
core/java/android/content/IClipboard.aidl \
core/java/android/content/IContentService.aidl \
core/java/android/content/IIntentReceiver.aidl \
@@ -468,7 +469,7 @@
## SDK version identifiers used in the published docs
# major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=3.1
+framework_docs_SDK_VERSION:=3.2
# release version (ie "Release x") (full releases only)
framework_docs_SDK_REL_ID:=1
diff --git a/api/14.txt b/api/14.txt
index 2a1bcac..895c44d 100644
--- a/api/14.txt
+++ b/api/14.txt
@@ -11206,7 +11206,7 @@
method public boolean hasError(int);
field public static final int SSL_EXPIRED = 1; // 0x1
field public static final int SSL_IDMISMATCH = 2; // 0x2
- field public static final int SSL_MAX_ERROR = 4; // 0x4
+ field public static final int SSL_MAX_ERROR = 6; // 0x6
field public static final int SSL_NOTYETVALID = 0; // 0x0
field public static final int SSL_UNTRUSTED = 3; // 0x3
}
diff --git a/api/current.txt b/api/current.txt
index e0e7565..91cf3fa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -117,6 +117,7 @@
field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
+ field public static final java.lang.String VPN = "android.permission.VPN";
field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK";
field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
field public static final java.lang.String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
@@ -185,18 +186,19 @@
public static final class R.attr {
ctor public R.attr();
field public static final int absListViewStyle = 16842858; // 0x101006a
- field public static final int accessibilityEventTypes = 16843647; // 0x101037f
- field public static final int accessibilityFeedbackType = 16843649; // 0x1010381
- field public static final int accessibilityFlags = 16843651; // 0x1010383
+ field public static final int accessibilityEventTypes = 16843646; // 0x101037e
+ field public static final int accessibilityFeedbackType = 16843648; // 0x1010380
+ field public static final int accessibilityFlags = 16843650; // 0x1010382
field public static final int accountPreferences = 16843423; // 0x101029f
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 = 16843669; // 0x1010395
+ field public static final int actionBarSplitStyle = 16843668; // 0x1010394
field public static final int actionBarStyle = 16843470; // 0x10102ce
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
+ field public static final int actionBarWidgetTheme = 16843683; // 0x10103a3
field public static final int actionButtonStyle = 16843480; // 0x10102d8
field public static final int actionDropDownStyle = 16843479; // 0x10102d7
field public static final int actionLayout = 16843515; // 0x10102fb
@@ -208,10 +210,10 @@
field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
field public static final int actionModeCutDrawable = 16843537; // 0x1010311
field public static final int actionModePasteDrawable = 16843539; // 0x1010313
- field public static final int actionModeSelectAllDrawable = 16843645; // 0x101037d
- field public static final int actionModeStyle = 16843681; // 0x10103a1
+ field public static final int actionModeSelectAllDrawable = 16843644; // 0x101037c
+ field public static final int actionModeStyle = 16843680; // 0x10103a0
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
- field public static final int actionProviderClass = 16843670; // 0x1010396
+ field public static final int actionProviderClass = 16843669; // 0x1010395
field public static final int actionViewClass = 16843516; // 0x10102fc
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -223,7 +225,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 = 16843639; // 0x1010377
+ field public static final int alignmentMode = 16843638; // 0x1010376
field public static final int allContactsName = 16843468; // 0x10102cc
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
@@ -257,8 +259,8 @@
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
- field public static final int backgroundSplit = 16843672; // 0x1010398
- field public static final int backgroundStacked = 16843671; // 0x1010397
+ field public static final int backgroundSplit = 16843671; // 0x1010397
+ field public static final int backgroundStacked = 16843670; // 0x1010396
field public static final int backupAgent = 16843391; // 0x101027f
field public static final int baseline = 16843548; // 0x101031c
field public static final int baselineAlignBottom = 16843042; // 0x1010122
@@ -267,7 +269,7 @@
field public static final int borderlessButtonStyle = 16843563; // 0x101032b
field public static final int bottom = 16843184; // 0x10101b0
field public static final int bottomBright = 16842957; // 0x10100cd
- field public static final int bottomChevronDrawable = 16843658; // 0x101038a
+ field public static final int bottomChevronDrawable = 16843657; // 0x1010389
field public static final int bottomDark = 16842953; // 0x10100c9
field public static final int bottomLeftRadius = 16843179; // 0x10101ab
field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -286,7 +288,7 @@
field public static final int cacheColorHint = 16843009; // 0x1010101
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
- field public static final int canRetrieveWindowContent = 16843652; // 0x1010384
+ field public static final int canRetrieveWindowContent = 16843651; // 0x1010383
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int centerBright = 16842956; // 0x10100cc
@@ -315,18 +317,18 @@
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
- field public static final int colorActivatedHighlight = 16843677; // 0x101039d
+ field public static final int colorActivatedHighlight = 16843676; // 0x101039c
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
- field public static final int colorFocusedHighlight = 16843676; // 0x101039c
+ field public static final int colorFocusedHighlight = 16843675; // 0x101039b
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
- field public static final int colorLongPressedHighlight = 16843675; // 0x101039b
- field public static final int colorMultiSelectHighlight = 16843678; // 0x101039e
- field public static final int colorPressedHighlight = 16843674; // 0x101039a
- field public static final int columnCount = 16843636; // 0x1010374
+ field public static final int colorLongPressedHighlight = 16843674; // 0x101039a
+ field public static final int colorMultiSelectHighlight = 16843677; // 0x101039d
+ field public static final int colorPressedHighlight = 16843673; // 0x1010399
+ field public static final int columnCount = 16843635; // 0x1010373
field public static final int columnDelay = 16843215; // 0x10101cf
- field public static final int columnOrderPreserved = 16843637; // 0x1010375
+ field public static final int columnOrderPreserved = 16843636; // 0x1010374
field public static final int columnWidth = 16843031; // 0x1010117
field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
field public static final int completionHint = 16843122; // 0x1010172
@@ -380,11 +382,11 @@
field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
field public static final int drawable = 16843161; // 0x1010199
field public static final int drawableBottom = 16843118; // 0x101016e
- field public static final int drawableEnd = 16843680; // 0x10103a0
+ field public static final int drawableEnd = 16843679; // 0x101039f
field public static final int drawableLeft = 16843119; // 0x101016f
field public static final int drawablePadding = 16843121; // 0x1010171
field public static final int drawableRight = 16843120; // 0x1010170
- field public static final int drawableStart = 16843679; // 0x101039f
+ field public static final int drawableStart = 16843678; // 0x101039e
field public static final int drawableTop = 16843117; // 0x101016d
field public static final int drawingCacheQuality = 16842984; // 0x10100e8
field public static final int dropDownAnchor = 16843363; // 0x1010263
@@ -441,7 +443,7 @@
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
- field public static final int feedbackCount = 16843664; // 0x1010390
+ field public static final int feedbackCount = 16843663; // 0x101038f
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillBefore = 16843196; // 0x10101bc
field public static final int fillEnabled = 16843343; // 0x101024f
@@ -494,7 +496,7 @@
field public static final int hand_hour = 16843011; // 0x1010103
field public static final int hand_minute = 16843012; // 0x1010104
field public static final int handle = 16843354; // 0x101025a
- field public static final int handleDrawable = 16843654; // 0x1010386
+ field public static final int handleDrawable = 16843653; // 0x1010385
field public static final int handleProfiling = 16842786; // 0x1010022
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
field public static final int hardwareAccelerated = 16843475; // 0x10102d3
@@ -503,12 +505,12 @@
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int height = 16843093; // 0x1010155
field public static final int hint = 16843088; // 0x1010150
- field public static final int hitRadius = 16843661; // 0x101038d
+ field public static final int hitRadius = 16843660; // 0x101038c
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
field public static final int homeLayout = 16843549; // 0x101031d
field public static final int horizontalDivider = 16843053; // 0x101012d
field public static final int horizontalGap = 16843327; // 0x101023f
- field public static final int horizontalOffset = 16843666; // 0x1010392
+ field public static final int horizontalOffset = 16843665; // 0x1010391
field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
field public static final int horizontalSpacing = 16843028; // 0x1010114
field public static final int host = 16842792; // 0x1010028
@@ -554,7 +556,7 @@
field public static final int installLocation = 16843447; // 0x10102b7
field public static final int interpolator = 16843073; // 0x1010141
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
- field public static final int isAuxiliary = 16843646; // 0x101037e
+ field public static final int isAuxiliary = 16843645; // 0x101037d
field public static final int isDefault = 16843297; // 0x1010221
field public static final int isIndicator = 16843079; // 0x1010147
field public static final int isModifier = 16843334; // 0x1010246
@@ -607,8 +609,8 @@
field public static final int layout_centerInParent = 16843151; // 0x101018f
field public static final int layout_centerVertical = 16843153; // 0x1010191
field public static final int layout_column = 16843084; // 0x101014c
- field public static final int layout_columnFlexibility = 16843644; // 0x101037c
- field public static final int layout_columnSpan = 16843643; // 0x101037b
+ field public static final deprecated int layout_columnFlexibility = 16843643; // 0x101037b
+ field public static final int layout_columnSpan = 16843642; // 0x101037a
field public static final int layout_gravity = 16842931; // 0x10100b3
field public static final int layout_height = 16842997; // 0x10100f5
field public static final int layout_margin = 16842998; // 0x10100f6
@@ -616,9 +618,9 @@
field public static final int layout_marginLeft = 16842999; // 0x10100f7
field public static final int layout_marginRight = 16843001; // 0x10100f9
field public static final int layout_marginTop = 16843000; // 0x10100f8
- field public static final int layout_row = 16843640; // 0x1010378
- field public static final int layout_rowFlexibility = 16843642; // 0x101037a
- field public static final int layout_rowSpan = 16843641; // 0x1010379
+ field public static final int layout_row = 16843639; // 0x1010377
+ field public static final deprecated int layout_rowFlexibility = 16843641; // 0x1010379
+ field public static final int layout_rowSpan = 16843640; // 0x1010378
field public static final int layout_scale = 16843155; // 0x1010193
field public static final int layout_span = 16843085; // 0x101014d
field public static final int layout_toLeftOf = 16843138; // 0x1010182
@@ -628,7 +630,7 @@
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int leftChevronDrawable = 16843655; // 0x1010387
+ field public static final int leftChevronDrawable = 16843654; // 0x1010386
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -640,8 +642,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 = 16843667; // 0x1010393
- field public static final int listPreferredItemHeightSmall = 16843668; // 0x1010394
+ field public static final int listPreferredItemHeightLarge = 16843666; // 0x1010392
+ field public static final int listPreferredItemHeightSmall = 16843667; // 0x1010393
field public static final int listSelector = 16843003; // 0x10100fb
field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208
field public static final int listViewStyle = 16842868; // 0x1010074
@@ -672,8 +674,8 @@
field public static final int minHeight = 16843072; // 0x1010140
field public static final int minLevel = 16843185; // 0x10101b1
field public static final int minLines = 16843094; // 0x1010156
- field public static final int minResizeHeight = 16843683; // 0x10103a3
- field public static final int minResizeWidth = 16843682; // 0x10103a2
+ field public static final int minResizeHeight = 16843682; // 0x10103a2
+ field public static final int minResizeWidth = 16843681; // 0x10103a1
field public static final int minSdkVersion = 16843276; // 0x101020c
field public static final int minWidth = 16843071; // 0x101013f
field public static final int mode = 16843134; // 0x101017e
@@ -689,7 +691,7 @@
field public static final int nextFocusUp = 16842979; // 0x10100e3
field public static final int noHistory = 16843309; // 0x101022d
field public static final int normalScreens = 16843397; // 0x1010285
- field public static final int notificationTimeout = 16843650; // 0x1010382
+ field public static final int notificationTimeout = 16843649; // 0x1010381
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -703,11 +705,11 @@
field public static final int orderingFromXml = 16843239; // 0x10101e7
field public static final int orientation = 16842948; // 0x10100c4
field public static final int outAnimation = 16843128; // 0x1010178
- field public static final int outerRadius = 16843660; // 0x101038c
+ field public static final int outerRadius = 16843659; // 0x101038b
field public static final int overScrollFooter = 16843459; // 0x10102c3
field public static final int overScrollHeader = 16843458; // 0x10102c2
field public static final int overScrollMode = 16843457; // 0x10102c1
- field public static final int packageNames = 16843648; // 0x1010380
+ field public static final int packageNames = 16843647; // 0x101037f
field public static final int padding = 16842965; // 0x10100d5
field public static final int paddingBottom = 16842969; // 0x10100d9
field public static final int paddingLeft = 16842966; // 0x10100d6
@@ -792,17 +794,17 @@
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int right = 16843183; // 0x10101af
- field public static final int rightChevronDrawable = 16843656; // 0x1010388
+ field public static final int rightChevronDrawable = 16843655; // 0x1010387
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
field public static final int rotation = 16843558; // 0x1010326
field public static final int rotationX = 16843559; // 0x1010327
field public static final int rotationY = 16843560; // 0x1010328
- field public static final int rowCount = 16843634; // 0x1010372
+ field public static final int rowCount = 16843633; // 0x1010371
field public static final int rowDelay = 16843216; // 0x10101d0
field public static final int rowEdgeFlags = 16843329; // 0x1010241
field public static final int rowHeight = 16843058; // 0x1010132
- field public static final int rowOrderPreserved = 16843635; // 0x1010373
+ field public static final int rowOrderPreserved = 16843634; // 0x1010372
field public static final int saveEnabled = 16842983; // 0x10100e7
field public static final int scaleGravity = 16843262; // 0x10101fe
field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -868,7 +870,7 @@
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
- field public static final int snapMargin = 16843663; // 0x101038f
+ field public static final int snapMargin = 16843662; // 0x101038e
field public static final int soundEffectsEnabled = 16843285; // 0x1010215
field public static final int spacing = 16843027; // 0x1010113
field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -916,7 +918,7 @@
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int suggestActionMsg = 16843228; // 0x10101dc
field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
- field public static final int suggestionsEnabled = 16843633; // 0x1010371
+ field public static final int suggestionsEnabled = 16843632; // 0x1010370
field public static final int summary = 16843241; // 0x10101e9
field public static final int summaryColumn = 16843426; // 0x10102a2
field public static final int summaryOff = 16843248; // 0x10101f0
@@ -933,7 +935,7 @@
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
field public static final int targetClass = 16842799; // 0x101002f
- field public static final int targetDrawables = 16843653; // 0x1010385
+ field public static final int targetDrawables = 16843652; // 0x1010384
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
@@ -948,7 +950,7 @@
field public static final int tension = 16843370; // 0x101026a
field public static final int testOnly = 16843378; // 0x1010272
field public static final int text = 16843087; // 0x101014f
- field public static final int textAllCaps = 16843673; // 0x1010399
+ field public static final int textAllCaps = 16843672; // 0x1010398
field public static final int textAppearance = 16842804; // 0x1010034
field public static final int textAppearanceButton = 16843271; // 0x1010207
field public static final int textAppearanceInverse = 16842805; // 0x1010035
@@ -989,8 +991,7 @@
field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
- field public static final int textEditSuggestionItemLayout = 16843632; // 0x1010370
- field public static final int textEditSuggestionsWindowLayout = 16843631; // 0x101036f
+ field public static final int textEditSuggestionItemLayout = 16843631; // 0x101036f
field public static final int textFilterEnabled = 16843007; // 0x10100ff
field public static final int textIsSelectable = 16843542; // 0x1010316
field public static final int textOff = 16843045; // 0x1010125
@@ -1023,7 +1024,7 @@
field public static final int toYScale = 16843205; // 0x10101c5
field public static final int top = 16843182; // 0x10101ae
field public static final int topBright = 16842955; // 0x10100cb
- field public static final int topChevronDrawable = 16843657; // 0x1010389
+ field public static final int topChevronDrawable = 16843656; // 0x1010388
field public static final int topDark = 16842951; // 0x10100c7
field public static final int topLeftRadius = 16843177; // 0x10101a9
field public static final int topOffset = 16843352; // 0x1010258
@@ -1039,7 +1040,7 @@
field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
- field public static final int useDefaultMargins = 16843638; // 0x1010376
+ field public static final int useDefaultMargins = 16843637; // 0x1010375
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
field public static final int userVisible = 16843409; // 0x1010291
@@ -1053,10 +1054,10 @@
field public static final int verticalCorrection = 16843322; // 0x101023a
field public static final int verticalDivider = 16843054; // 0x101012e
field public static final int verticalGap = 16843328; // 0x1010240
- field public static final int verticalOffset = 16843665; // 0x1010391
+ field public static final int verticalOffset = 16843664; // 0x1010390
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
- field public static final int vibrationDuration = 16843662; // 0x101038e
+ field public static final int vibrationDuration = 16843661; // 0x101038d
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1073,7 +1074,7 @@
field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
- field public static final int waveDrawable = 16843659; // 0x101038b
+ field public static final int waveDrawable = 16843658; // 0x101038a
field public static final int webTextViewStyle = 16843449; // 0x10102b9
field public static final int webViewStyle = 16842885; // 0x1010085
field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -1828,6 +1829,7 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DEFAULT = 1; // 0x1
+ field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
field public static final int FEEDBACK_AUDIBLE = 4; // 0x4
field public static final int FEEDBACK_GENERIC = 16; // 0x10
field public static final int FEEDBACK_HAPTIC = 2; // 0x2
@@ -2242,6 +2244,7 @@
method public abstract java.lang.CharSequence getSubtitle();
method public abstract android.app.ActionBar.Tab getTabAt(int);
method public abstract int getTabCount();
+ method public android.content.Context getThemedContext();
method public abstract java.lang.CharSequence getTitle();
method public abstract void hide();
method public abstract boolean isShowing();
@@ -2262,7 +2265,7 @@
method public abstract void setDisplayShowHomeEnabled(boolean);
method public abstract void setDisplayShowTitleEnabled(boolean);
method public abstract void setDisplayUseLogoEnabled(boolean);
- method public abstract void setHomeButtonEnabled(boolean);
+ method public void setHomeButtonEnabled(boolean);
method public abstract void setIcon(int);
method public abstract void setIcon(android.graphics.drawable.Drawable);
method public abstract void setListNavigationCallbacks(android.widget.SpinnerAdapter, android.app.ActionBar.OnNavigationListener);
@@ -11445,6 +11448,26 @@
method public abstract java.lang.String sanitize(java.lang.String);
}
+ public class VpnBuilder {
+ ctor public VpnBuilder();
+ method public android.net.VpnBuilder addAddress(java.lang.String, int);
+ method public android.net.VpnBuilder addAddress(java.net.InetAddress, int);
+ method public android.net.VpnBuilder addDnsServer(java.lang.String);
+ method public android.net.VpnBuilder addDnsServer(java.net.InetAddress);
+ method public android.net.VpnBuilder addRoute(java.lang.String, int);
+ method public android.net.VpnBuilder addRoute(java.net.InetAddress, int);
+ method public android.net.VpnBuilder addSearchDomain(java.lang.String);
+ method public android.os.ParcelFileDescriptor establish();
+ method public static android.content.Intent prepare(android.content.Context);
+ method public static boolean protect(int);
+ method public static boolean protect(java.net.Socket);
+ method public static boolean protect(java.net.DatagramSocket);
+ method public android.net.VpnBuilder setConfigureIntent(android.app.PendingIntent);
+ method public android.net.VpnBuilder setMtu(int);
+ method public android.net.VpnBuilder setSession(java.lang.String);
+ field public static final java.lang.String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED";
+ }
+
}
package android.net.http {
@@ -11520,9 +11543,11 @@
method public int getPrimaryError();
method public java.lang.String getUrl();
method public boolean hasError(int);
+ field public static final int SSL_DATE_INVALID = 4; // 0x4
field public static final int SSL_EXPIRED = 1; // 0x1
field public static final int SSL_IDMISMATCH = 2; // 0x2
- field public static final int SSL_MAX_ERROR = 4; // 0x4
+ field public static final int SSL_INVALID = 5; // 0x5
+ field public static final deprecated int SSL_MAX_ERROR = 6; // 0x6
field public static final int SSL_NOTYETVALID = 0; // 0x0
field public static final int SSL_UNTRUSTED = 3; // 0x3
}
@@ -15306,6 +15331,7 @@
field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
field public static final java.lang.String DURATION = "duration";
field public static final int INCOMING_TYPE = 1; // 0x1
+ field public static final java.lang.String IS_READ = "is_read";
field public static final int MISSED_TYPE = 3; // 0x3
field public static final java.lang.String NEW = "new";
field public static final java.lang.String NUMBER = "number";
@@ -16060,6 +16086,7 @@
field public static final java.lang.String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE";
field public static final java.lang.String EXTRA_CREATE_DESCRIPTION = "com.android.contacts.action.CREATE_DESCRIPTION";
field public static final java.lang.String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE";
+ field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
field public static final java.lang.String SEARCH_SUGGESTION_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";
field public static final java.lang.String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";
field public static final java.lang.String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED = "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";
@@ -16642,6 +16669,7 @@
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
+ field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
@@ -16710,7 +16738,7 @@
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
- field public static final java.lang.String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
+ field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
@@ -16955,9 +16983,9 @@
field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
field public static final java.lang.String DURATION = "duration";
field public static final java.lang.String HAS_CONTENT = "has_content";
+ field public static final java.lang.String IS_READ = "is_read";
field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
field public static final java.lang.String MIME_TYPE = "mime_type";
- field public static final java.lang.String NEW = "new";
field public static final java.lang.String NUMBER = "number";
field public static final java.lang.String SOURCE_DATA = "source_data";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
@@ -17044,6 +17072,7 @@
public class BaseObj {
method public synchronized void destroy();
+ method public java.lang.String getName();
method public void setName(java.lang.String);
}
@@ -17696,6 +17725,21 @@
method public void surfaceDestroyed(android.view.SurfaceHolder);
}
+ public class RSTextureView extends android.view.TextureView implements android.view.TextureView.SurfaceTextureListener {
+ ctor public RSTextureView(android.content.Context);
+ ctor public RSTextureView(android.content.Context, android.util.AttributeSet);
+ method public android.renderscript.RenderScriptGL createRenderScriptGL(android.renderscript.RenderScriptGL.SurfaceConfig);
+ method public void destroyRenderScriptGL();
+ method public android.renderscript.RenderScriptGL getRenderScriptGL();
+ method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
+ method public void onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
+ method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+ method public void pause();
+ method public void resume();
+ method public void setRenderScriptGL(android.renderscript.RenderScriptGL);
+ }
+
public class RenderScript {
method public void contextDump();
method public static android.renderscript.RenderScript create(android.content.Context);
@@ -17743,6 +17787,7 @@
method public void pause();
method public void resume();
method public void setSurface(android.view.SurfaceHolder, int, int);
+ method public void setSurfaceTexture(android.graphics.SurfaceTexture, int, int);
}
public static class RenderScriptGL.SurfaceConfig {
@@ -17786,6 +17831,7 @@
public class Script extends android.renderscript.BaseObj {
method public void bindAllocation(android.renderscript.Allocation, int);
+ method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker);
method protected void invoke(int);
method protected void invoke(int, android.renderscript.FieldPacker);
method public void setTimeZone(java.lang.String);
@@ -21918,9 +21964,8 @@
field public static final int EDGE_TOP = 1; // 0x1
field public static final int FLAG_WINDOW_IS_OBSCURED = 1; // 0x1
field public static final int INVALID_POINTER_ID = -1; // 0xffffffff
+ field public static final int TOOL_TYPE_ERASER = 4; // 0x4
field public static final int TOOL_TYPE_FINGER = 1; // 0x1
- field public static final int TOOL_TYPE_INDIRECT_FINGER = 4; // 0x4
- field public static final int TOOL_TYPE_INDIRECT_STYLUS = 5; // 0x5
field public static final int TOOL_TYPE_MOUSE = 3; // 0x3
field public static final int TOOL_TYPE_STYLUS = 2; // 0x2
field public static final int TOOL_TYPE_UNKNOWN = 0; // 0x0
@@ -22232,6 +22277,7 @@
method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence);
method protected boolean fitSystemWindows(android.graphics.Rect);
+ method public boolean fitsSystemWindows();
method public android.view.View focusSearch(int);
method public void forceLayout();
method public float getAlpha();
@@ -22473,6 +22519,7 @@
method public void setEnabled(boolean);
method public void setFadingEdgeLength(int);
method public void setFilterTouchesWhenObscured(boolean);
+ method public void setFitsSystemWindows(boolean);
method public void setFocusable(boolean);
method public void setFocusableInTouchMode(boolean);
method public void setHapticFeedbackEnabled(boolean);
@@ -24683,6 +24730,7 @@
method public void beforeTextChanged(java.lang.CharSequence, int, int, int);
method public void clearChoices();
method public void clearTextFilter();
+ method public void deferNotifyDataSetChanged();
method public int getCacheColorHint();
method public int getCheckedItemCount();
method public long[] getCheckedItemIds();
@@ -24898,6 +24946,7 @@
ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet);
ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet, int);
method public void advance();
+ method public void deferNotifyDataSetChanged();
method public void fyiWillBeAdvancedByHostKThx();
method public android.widget.Adapter getAdapter();
method public android.view.View getCurrentView();
@@ -25435,15 +25484,14 @@
method public void setRowCount(int);
method public void setRowOrderPreserved(boolean);
method public void setUseDefaultMargins(boolean);
- method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment, int);
- method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment, int);
method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment);
method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment);
+ method public static android.widget.GridLayout.Spec spec(int, int);
+ method public static android.widget.GridLayout.Spec spec(int);
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 int CAN_STRETCH = 2; // 0x2
field public static final android.widget.GridLayout.Alignment CENTER;
field public static final android.widget.GridLayout.Alignment FILL;
field public static final int HORIZONTAL = 0; // 0x0
@@ -26198,7 +26246,7 @@
method public int timePassed();
}
- public class SearchView extends android.widget.LinearLayout {
+ public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView {
ctor public SearchView(android.content.Context);
ctor public SearchView(android.content.Context, android.util.AttributeSet);
method public java.lang.CharSequence getQuery();
@@ -26207,6 +26255,8 @@
method public boolean isIconified();
method public boolean isQueryRefinementEnabled();
method public boolean isSubmitButtonEnabled();
+ method public void onActionViewCollapsed();
+ method public void onActionViewExpanded();
method public void setIconified(boolean);
method public void setIconifiedByDefault(boolean);
method public void setMaxWidth(int);
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 4926db2..52b2d91 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -113,8 +113,8 @@
dump_file("NETWORK ROUTES", "/proc/net/route");
dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
dump_file("ARP CACHE", "/proc/net/arp");
- run_command("IPTABLES", 10, "su", "root", "iptables", "-L", NULL);
- run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", NULL);
+ run_command("IPTABLES", 10, "su", "root", "iptables", "-L", "-n", NULL);
+ run_command("IPTABLE NAT", 10, "su", "root", "iptables", "-t", "nat", "-L", "-n", NULL);
run_command("WIFI NETWORKS", 20,
"su", "root", "wpa_cli", "list_networks", NULL);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 68c9926..1e238f0 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -130,20 +130,11 @@
* 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_WINDOW_STATE_CHANGED},
* {@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.
+ * In other words, the last window that was shown or the last window that the user has touched
+ * during touch exploration.
* </p>
* <p>
* The entry point for retrieving window content is through calling
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index a09607a..41a3eaca 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -75,6 +75,17 @@
public static final int FEEDBACK_GENERIC = 0x0000010;
/**
+ * Mask for all feedback types.
+ *
+ * @see #FEEDBACK_SPOKEN
+ * @see #FEEDBACK_HAPTIC
+ * @see #FEEDBACK_AUDIBLE
+ * @see #FEEDBACK_VISUAL
+ * @see #FEEDBACK_GENERIC
+ */
+ public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
+
+ /**
* If an {@link AccessibilityService} is the default for a given type.
* Default service is invoked only if no package specific one exists. In case of
* more than one package specific service only the earlier registered is notified.
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 36940c2..7acaec8 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -29,10 +29,16 @@
import android.widget.SpinnerAdapter;
/**
- * This is the public interface to the contextual ActionBar.
- * The ActionBar acts as a replacement for the title bar in Activities.
- * It provides facilities for creating toolbar actions as well as
- * methods of navigating around an application.
+ * Acts as a replacement for the title bar in Activities.
+ * The action bar provides facilities for creating toolbar actions as well as
+ * methods of navigating the application.
+ * <p>By default, the action bar appears at the top of every activity, with the application icon on
+ * the left, followed by the activity title. Items from the activity's options menu are also
+ * accessible from the action bar.</p>
+ * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
+ * android.app.Activity#getActionBar getActionBar()}.</p>
+ * <p>For more information, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
+ * Bar</a> developer guide.</p>
*/
public abstract class ActionBar {
/**
@@ -621,7 +627,18 @@
*
* @param enabled true to enable the home button, false to disable the home button.
*/
- public abstract void setHomeButtonEnabled(boolean enabled);
+ public void setHomeButtonEnabled(boolean enabled) { }
+
+ /**
+ * Returns a {@link Context} with an appropriate theme for creating views that
+ * will appear in the action bar. If you are inflating or instantiating custom views
+ * that will appear in an action bar, you should use the Context returned by this method.
+ * (This includes adapters used for list navigation mode.)
+ * This will ensure that views contrast properly against the action bar.
+ *
+ * @return A themed Context for creating views
+ */
+ public Context getThemedContext() { return null; }
/**
* Listener interface for ActionBar navigation events.
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aeb16f4..fb1570e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -32,6 +32,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.content.res.Resources.Theme;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -54,6 +55,7 @@
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -672,6 +674,7 @@
/*package*/ int mConfigChangeFlags;
/*package*/ Configuration mCurrentConfig;
private SearchManager mSearchManager;
+ private MenuInflater mMenuInflater;
static final class NonConfigurationInstances {
Object activity;
@@ -1400,16 +1403,18 @@
public void onConfigurationChanged(Configuration newConfig) {
mCalled = true;
- if (mActionBar != null) {
- mActionBar.onConfigurationChanged(newConfig);
- }
-
mFragments.dispatchConfigurationChanged(newConfig);
if (mWindow != null) {
// Pass the configuration changed event to the window
mWindow.onConfigurationChanged(newConfig);
}
+
+ if (mActionBar != null) {
+ // Do this last; the action bar will need to access
+ // view changes from above.
+ mActionBar.onConfigurationChanged(newConfig);
+ }
}
/**
@@ -1593,10 +1598,10 @@
//Log.v(TAG, "invalidateFragmentIndex: index=" + index);
if (mAllLoaderManagers != null) {
LoaderManagerImpl lm = mAllLoaderManagers.get(index);
- if (lm != null) {
+ if (lm != null && !lm.mRetaining) {
lm.doDestroy();
+ mAllLoaderManagers.remove(index);
}
- mAllLoaderManagers.remove(index);
}
}
@@ -3083,7 +3088,16 @@
* Returns a {@link MenuInflater} with this context.
*/
public MenuInflater getMenuInflater() {
- return new MenuInflater(this);
+ // Make sure that action views can get an appropriate theme.
+ if (mMenuInflater == null) {
+ initActionBar();
+ if (mActionBar != null) {
+ mMenuInflater = new MenuInflater(mActionBar.getThemedContext());
+ } else {
+ mMenuInflater = new MenuInflater(this);
+ }
+ }
+ return mMenuInflater;
}
@Override
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9bbbd6c..1e93f88 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -123,7 +123,6 @@
/** @hide */
public static final String TAG = "ActivityThread";
private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
- private static final boolean DEBUG = false;
static final boolean localLOGV = false;
static final boolean DEBUG_MESSAGES = false;
/** @hide */
@@ -163,7 +162,7 @@
= new ArrayList<Application>();
// set of instantiated backup agents, keyed by package name
final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
- static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal();
+ static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
Instrumentation mInstrumentation;
String mInstrumentationAppDir = null;
String mInstrumentationAppPackage = null;
@@ -410,9 +409,9 @@
CompatibilityInfo info;
}
- native private void dumpGraphicsInfo(FileDescriptor fd);
+ private native void dumpGraphicsInfo(FileDescriptor fd);
- private final class ApplicationThread extends ApplicationThreadNative {
+ private class ApplicationThread extends ApplicationThreadNative {
private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%21s %8d";
private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
@@ -734,13 +733,13 @@
FileOutputStream fout = new FileOutputStream(fd);
PrintWriter pw = new PrintWriter(fout);
try {
- return dumpMemInfo(fd, pw, args);
+ return dumpMemInfo(pw, args);
} finally {
pw.flush();
}
}
- private Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, PrintWriter pw, String[] args) {
+ private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, String[] args) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -754,7 +753,7 @@
long dalvikFree = runtime.freeMemory() / 1024;
long dalvikAllocated = dalvikMax - dalvikFree;
long viewInstanceCount = ViewDebug.getViewInstanceCount();
- long viewRootInstanceCount = ViewDebug.getViewAncestorInstanceCount();
+ long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
int globalAssetCount = AssetManager.getGlobalAssetCount();
@@ -868,7 +867,7 @@
int otherPrivateDirty = memInfo.otherPrivateDirty;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
- printRow(pw, HEAP_COLUMN, memInfo.getOtherLabel(i),
+ printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i),
memInfo.getOtherPrivateDirty(i), "", "", "");
otherPss -= memInfo.getOtherPss(i);
@@ -885,7 +884,7 @@
pw.println(" ");
pw.println(" Objects");
- printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewAncestors:",
+ printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
viewRootInstanceCount);
printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
@@ -937,6 +936,7 @@
@Override
public void dumpGfxInfo(FileDescriptor fd, String[] args) {
dumpGraphicsInfo(fd);
+ WindowManagerImpl.getDefault().dumpGfxInfo(fd);
}
private void printRow(PrintWriter pw, String format, Object...objs) {
@@ -959,7 +959,7 @@
}
}
- private final class H extends Handler {
+ private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
@@ -1220,7 +1220,7 @@
}
}
- private final class Idler implements MessageQueue.IdleHandler {
+ private class Idler implements MessageQueue.IdleHandler {
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
if (a != null) {
@@ -1231,12 +1231,13 @@
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
- (a.activity != null ? a.activity.mFinished : false));
+ (a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig);
a.createdConfig = null;
} catch (RemoteException ex) {
+ // Ignore
}
}
prev = a;
@@ -1256,7 +1257,7 @@
}
}
- private final static class ResourcesKey {
+ private static class ResourcesKey {
final private String mResDir;
final private float mScale;
final private int mHash;
@@ -1282,17 +1283,17 @@
}
}
- public static final ActivityThread currentActivityThread() {
+ public static ActivityThread currentActivityThread() {
return sThreadLocal.get();
}
- public static final String currentPackageName() {
+ public static String currentPackageName() {
ActivityThread am = currentActivityThread();
return (am != null && am.mBoundApplication != null)
? am.mBoundApplication.processName : null;
}
- public static final Application currentApplication() {
+ public static Application currentApplication() {
ActivityThread am = currentActivityThread();
return am != null ? am.mInitialApplication : null;
}
@@ -1337,7 +1338,7 @@
return config;
}
- private final Configuration mMainThreadConfig = new Configuration();
+ private Configuration mMainThreadConfig = new Configuration();
Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) {
if (config == null) {
return null;
@@ -1456,6 +1457,7 @@
ai = getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_SHARED_LIBRARY_FILES);
} catch (RemoteException e) {
+ // Ignore
}
if (ai != null) {
@@ -1505,7 +1507,7 @@
}
}
- private final LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
+ private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
synchronized (mPackages) {
WeakReference<LoadedApk> ref;
@@ -1712,15 +1714,15 @@
// if the thread hasn't started yet, we don't have the handler, so just
// save the messages until we're ready.
- private final void queueOrSendMessage(int what, Object obj) {
+ private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
- private final void queueOrSendMessage(int what, Object obj, int arg1) {
+ private void queueOrSendMessage(int what, Object obj, int arg1) {
queueOrSendMessage(what, obj, arg1, 0);
}
- private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
+ private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
@@ -1743,7 +1745,7 @@
queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
}
- private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
@@ -1861,7 +1863,7 @@
return activity;
}
- private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
+ private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -1917,11 +1919,12 @@
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null);
} catch (RemoteException ex) {
+ // Ignore
}
}
}
- private final void deliverNewIntents(ActivityClientRecord r,
+ private void deliverNewIntents(ActivityClientRecord r,
List<Intent> intents) {
final int N = intents.size();
for (int i=0; i<N; i++) {
@@ -1949,7 +1952,7 @@
}
}
- private final void handleNewIntent(NewIntentData data) {
+ private void handleNewIntent(NewIntentData data) {
performNewIntents(data.token, data.intents);
}
@@ -1964,7 +1967,7 @@
return sCurrentBroadcastIntent.get();
}
- private final void handleReceiver(ReceiverData data) {
+ private void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -1976,7 +1979,7 @@
IActivityManager mgr = ActivityManagerNative.getDefault();
- BroadcastReceiver receiver = null;
+ BroadcastReceiver receiver;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
@@ -2026,7 +2029,7 @@
}
// Instantiate a BackupAgent and tell it that it's alive
- private final void handleCreateBackupAgent(CreateBackupAgentData data) {
+ private void handleCreateBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
// no longer idle; we have backup work to do
@@ -2091,7 +2094,7 @@
}
// Tear down a BackupAgent
- private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
+ private void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
@@ -2110,7 +2113,7 @@
}
}
- private final void handleCreateService(CreateServiceData data) {
+ private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -2156,7 +2159,7 @@
}
}
- private final void handleBindService(BindServiceData data) {
+ private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
@@ -2184,7 +2187,7 @@
}
}
- private final void handleUnbindService(BindServiceData data) {
+ private void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
@@ -2236,7 +2239,7 @@
}
}
- private final void handleServiceArgs(ServiceArgsData data) {
+ private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
@@ -2270,7 +2273,7 @@
}
}
- private final void handleStopService(IBinder token) {
+ private void handleStopService(IBinder token) {
Service s = mServices.remove(token);
if (s != null) {
try {
@@ -2465,7 +2468,7 @@
private Bitmap mAvailThumbnailBitmap = null;
private Canvas mThumbnailCanvas = null;
- private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
+ private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
Bitmap thumbnail = mAvailThumbnailBitmap;
try {
if (thumbnail == null) {
@@ -2515,7 +2518,7 @@
return thumbnail;
}
- private final void handlePauseActivity(IBinder token, boolean finished,
+ private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
@@ -2621,7 +2624,7 @@
CharSequence description;
}
- private final class ProviderRefCount {
+ private class ProviderRefCount {
public int count;
ProviderRefCount(int pCount) {
count = pCount;
@@ -2636,7 +2639,7 @@
* For the client, we want to call onStop()/onStart() to indicate when
* the activity's UI visibillity changes.
*/
- private final void performStopActivityInner(ActivityClientRecord r,
+ private void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown, boolean saveState) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
Bundle state = null;
@@ -2699,7 +2702,7 @@
}
}
- private final void updateVisibility(ActivityClientRecord r, boolean show) {
+ private void updateVisibility(ActivityClientRecord r, boolean show) {
View v = r.activity.mDecor;
if (v != null) {
if (show) {
@@ -2726,7 +2729,7 @@
}
}
- private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
+ private void handleStopActivity(IBinder token, boolean show, int configChanges) {
ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
@@ -2760,7 +2763,7 @@
}
}
- private final void handleWindowVisibility(IBinder token, boolean show) {
+ private void handleWindowVisibility(IBinder token, boolean show) {
ActivityClientRecord r = mActivities.get(token);
if (r == null) {
@@ -2785,7 +2788,7 @@
}
}
- private final void handleSleeping(IBinder token, boolean sleeping) {
+ private void handleSleeping(IBinder token, boolean sleeping) {
ActivityClientRecord r = mActivities.get(token);
if (r == null) {
@@ -2846,7 +2849,7 @@
WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
}
- private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
+ private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
final int N = results.size();
for (int i=0; i<N; i++) {
ResultInfo ri = results.get(i);
@@ -2869,7 +2872,7 @@
}
}
- private final void handleSendResult(ResultData res) {
+ private void handleSendResult(ResultData res) {
ActivityClientRecord r = mActivities.get(res.token);
if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
if (r != null) {
@@ -2915,7 +2918,7 @@
return performDestroyActivity(token, finishing, 0, false);
}
- private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
+ private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = mActivities.get(token);
Class activityClass = null;
@@ -3008,7 +3011,7 @@
return component == null ? "[Unknown]" : component.toShortString();
}
- private final void handleDestroyActivity(IBinder token, boolean finishing,
+ private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
@@ -3123,7 +3126,7 @@
}
}
- private final void handleRelaunchActivity(ActivityClientRecord tmp) {
+ private void handleRelaunchActivity(ActivityClientRecord tmp) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3233,7 +3236,7 @@
handleLaunchActivity(r, currentIntent);
}
- private final void handleRequestThumbnail(IBinder token) {
+ private void handleRequestThumbnail(IBinder token) {
ActivityClientRecord r = mActivities.get(token);
Bitmap thumbnail = createThumbnailBitmap(r);
CharSequence description = null;
@@ -3308,7 +3311,7 @@
return callbacks;
}
- private final void performConfigurationChanged(
+ private void performConfigurationChanged(
ComponentCallbacks cb, Configuration config) {
// Only for Activity objects, check that they actually call up to their
// superclass implementation. ComponentCallbacks is an interface, so
@@ -3451,6 +3454,9 @@
}
callbacks = collectComponentCallbacksLocked(false, config);
}
+
+ // Cleanup hardware accelerated stuff
+ WindowManagerImpl.getDefault().trimLocalMemory();
if (callbacks != null) {
final int N = callbacks.size();
@@ -3579,7 +3585,7 @@
WindowManagerImpl.getDefault().trimMemory(level);
}
- private final void handleBindApplication(AppBindData data) {
+ private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
@@ -3791,7 +3797,7 @@
}
}
- private final void installContentProviders(
+ private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
@@ -3825,7 +3831,7 @@
}
}
- private final IContentProvider getExistingProvider(Context context, String name) {
+ private IContentProvider getExistingProvider(Context context, String name) {
synchronized(mProviderMap) {
final ProviderClientRecord pr = mProviderMap.get(name);
if (pr != null) {
@@ -3835,7 +3841,7 @@
}
}
- private final IContentProvider getProvider(Context context, String name) {
+ private IContentProvider getProvider(Context context, String name) {
IContentProvider existing = getExistingProvider(context, name);
if (existing != null) {
return existing;
@@ -4007,7 +4013,7 @@
}
}
- private final IContentProvider installProvider(Context context,
+ private IContentProvider installProvider(Context context,
IContentProvider provider, ProviderInfo info, boolean noisy) {
ContentProvider localProvider = null;
if (provider == null) {
@@ -4027,6 +4033,7 @@
c = context.createPackageContext(ai.packageName,
Context.CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
+ // Ignore
}
}
if (c == null) {
@@ -4086,7 +4093,7 @@
return provider;
}
- private final void attach(boolean system) {
+ private void attach(boolean system) {
sThreadLocal.set(this);
mSystemThread = system;
if (!system) {
@@ -4101,6 +4108,7 @@
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
+ // Ignore
}
} else {
// Don't set application object here -- if the system crashes,
@@ -4166,7 +4174,7 @@
}
}
- public static final void main(String[] args) {
+ public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index e5a7980..93330a7 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -224,6 +224,12 @@
writer.print(" mExitAnim=#");
writer.println(Integer.toHexString(mExitAnim));
}
+ if (mPopEnterAnim != 0 || mPopExitAnim !=0) {
+ writer.print(prefix); writer.print("mPopEnterAnim=#");
+ writer.print(Integer.toHexString(mPopEnterAnim));
+ writer.print(" mPopExitAnim=#");
+ writer.println(Integer.toHexString(mPopExitAnim));
+ }
if (mBreadCrumbTitleRes != 0 || mBreadCrumbTitleText != null) {
writer.print(prefix); writer.print("mBreadCrumbTitleRes=#");
writer.print(Integer.toHexString(mBreadCrumbTitleRes));
@@ -248,13 +254,16 @@
writer.print(innerPrefix); writer.print("cmd="); writer.print(op.cmd);
writer.print(" fragment="); writer.println(op.fragment);
if (op.enterAnim != 0 || op.exitAnim != 0) {
- writer.print(prefix); writer.print("enterAnim="); writer.print(op.enterAnim);
- writer.print(" exitAnim="); writer.println(op.exitAnim);
+ writer.print(prefix); writer.print("enterAnim=#");
+ writer.print(Integer.toHexString(op.enterAnim));
+ writer.print(" exitAnim=#");
+ writer.println(Integer.toHexString(op.exitAnim));
}
if (op.popEnterAnim != 0 || op.popExitAnim != 0) {
- writer.print(prefix);
- writer.print("popEnterAnim="); writer.print(op.popEnterAnim);
- writer.print(" popExitAnim="); writer.println(op.popExitAnim);
+ writer.print(prefix); writer.print("popEnterAnim=#");
+ writer.print(Integer.toHexString(op.popEnterAnim));
+ writer.print(" popExitAnim=#");
+ writer.println(Integer.toHexString(op.popExitAnim));
}
if (op.removed != null && op.removed.size() > 0) {
for (int i=0; i<op.removed.size(); i++) {
@@ -695,11 +704,13 @@
} break;
case OP_DETACH: {
Fragment f = op.fragment;
+ f.mNextAnim = op.popEnterAnim;
mManager.attachFragment(f,
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
} break;
case OP_ATTACH: {
Fragment f = op.fragment;
+ f.mNextAnim = op.popExitAnim;
mManager.detachFragment(f,
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
} break;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index cb97c46..e2746d4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -162,6 +162,9 @@
* constructor to instantiate it. If the empty constructor is not available,
* a runtime exception will occur in some cases during state restore.
*
+ * <p>For more documentation, also see the <a
+ * href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
+ *
* <p>Topics covered here:
* <ol>
* <li><a href="#OlderPlatforms">Older Platforms</a>
@@ -880,7 +883,7 @@
public void setHasOptionsMenu(boolean hasMenu) {
if (mHasMenu != hasMenu) {
mHasMenu = hasMenu;
- if (isAdded() && !isHidden()) {
+ if (isAdded() && !isHidden() && isResumed()) {
mActivity.invalidateOptionsMenu();
}
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 789d3a6..24550c5 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -978,7 +978,7 @@
}
}
- if (mNeedMenuInvalidate && mActivity != null) {
+ if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
mActivity.invalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 436fdf8..58ea0c3 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -213,13 +213,13 @@
public void onFullBackup(FullBackupDataOutput data) throws IOException {
ApplicationInfo appInfo = getApplicationInfo();
- String rootDir = new File(appInfo.dataDir).getAbsolutePath();
- String filesDir = getFilesDir().getAbsolutePath();
- String databaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
- String sharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
- String cacheDir = getCacheDir().getAbsolutePath();
+ String rootDir = new File(appInfo.dataDir).getCanonicalPath();
+ String filesDir = getFilesDir().getCanonicalPath();
+ String databaseDir = getDatabasePath("foo").getParentFile().getCanonicalPath();
+ String sharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getCanonicalPath();
+ String cacheDir = getCacheDir().getCanonicalPath();
String libDir = (appInfo.nativeLibraryDir != null)
- ? new File(appInfo.nativeLibraryDir).getAbsolutePath()
+ ? new File(appInfo.nativeLibraryDir).getCanonicalPath()
: null;
// Filters, the scan queue, and the set of resulting entities
@@ -271,20 +271,27 @@
String spDir;
String cacheDir;
String libDir;
+ String filePath;
ApplicationInfo appInfo = getApplicationInfo();
- mainDir = new File(appInfo.dataDir).getAbsolutePath();
- filesDir = getFilesDir().getAbsolutePath();
- dbDir = getDatabasePath("foo").getParentFile().getAbsolutePath();
- spDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
- cacheDir = getCacheDir().getAbsolutePath();
- libDir = (appInfo.nativeLibraryDir == null) ? null
- : new File(appInfo.nativeLibraryDir).getAbsolutePath();
+ try {
+ mainDir = new File(appInfo.dataDir).getCanonicalPath();
+ filesDir = getFilesDir().getCanonicalPath();
+ dbDir = getDatabasePath("foo").getParentFile().getCanonicalPath();
+ spDir = getSharedPrefsFile("foo").getParentFile().getCanonicalPath();
+ cacheDir = getCacheDir().getCanonicalPath();
+ libDir = (appInfo.nativeLibraryDir == null)
+ ? null
+ : new File(appInfo.nativeLibraryDir).getCanonicalPath();
- // Now figure out which well-defined tree the file is placed in, working from
- // most to least specific. We also specifically exclude the lib and cache dirs.
- String filePath = file.getAbsolutePath();
+ // Now figure out which well-defined tree the file is placed in, working from
+ // most to least specific. We also specifically exclude the lib and cache dirs.
+ filePath = file.getCanonicalPath();
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to obtain canonical paths");
+ return;
+ }
if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) {
Log.w(TAG, "lib and cache files are not backed up");
@@ -334,15 +341,16 @@
while (scanQueue.size() > 0) {
File file = scanQueue.remove(0);
- String filePath = file.getAbsolutePath();
-
- // prune this subtree?
- if (excludes != null && excludes.contains(filePath)) {
- continue;
- }
-
- // If it's a directory, enqueue its contents for scanning.
+ String filePath;
try {
+ filePath = file.getCanonicalPath();
+
+ // prune this subtree?
+ if (excludes != null && excludes.contains(filePath)) {
+ continue;
+ }
+
+ // If it's a directory, enqueue its contents for scanning.
StructStat stat = Libcore.os.lstat(filePath);
if (OsConstants.S_ISLNK(stat.st_mode)) {
if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
@@ -355,6 +363,9 @@
}
}
}
+ } catch (IOException e) {
+ if (DEBUG) Log.w(TAG, "Error canonicalizing path of " + file);
+ continue;
} catch (ErrnoException e) {
if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e);
continue;
@@ -415,15 +426,15 @@
// Parse out the semantic domains into the correct physical location
if (domain.equals(FullBackup.DATA_TREE_TOKEN)) {
- basePath = getFilesDir().getAbsolutePath();
+ basePath = getFilesDir().getCanonicalPath();
} else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) {
- basePath = getDatabasePath("foo").getParentFile().getAbsolutePath();
+ basePath = getDatabasePath("foo").getParentFile().getCanonicalPath();
} else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) {
- basePath = new File(getApplicationInfo().dataDir).getAbsolutePath();
+ basePath = new File(getApplicationInfo().dataDir).getCanonicalPath();
} else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) {
- basePath = getSharedPrefsFile("foo").getParentFile().getAbsolutePath();
+ basePath = getSharedPrefsFile("foo").getParentFile().getCanonicalPath();
} else if (domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
- basePath = getCacheDir().getAbsolutePath();
+ basePath = getCacheDir().getCanonicalPath();
} else {
// Not a supported location
Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring");
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index bac874e..d645ac3 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -111,6 +111,23 @@
boolean isBackupEnabled();
/**
+ * Set the device's backup password. Returns {@code true} if the password was set
+ * successfully, {@code false} otherwise. Typically a failure means that an incorrect
+ * current password was supplied.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ */
+ boolean setBackupPassword(in String currentPw, in String newPw);
+
+ /**
+ * Reports whether a backup password is currently set. If not, then a null or empty
+ * "current password" argument should be passed to setBackupPassword().
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ */
+ boolean hasBackupPassword();
+
+ /**
* Schedule an immediate backup attempt for all pending updates. This is
* primarily intended for transports to use when they detect a suitable
* opportunity for doing a backup pass. If there are no pending updates to
@@ -161,9 +178,14 @@
* the same time, the UI supplies a callback Binder for progress notifications during
* the operation.
*
+ * <p>The password passed by the confirming entity must match the saved backup or
+ * full-device encryption password in order to perform a backup. If a password is
+ * supplied for restore, it must match the password used when creating the full
+ * backup dataset being used for restore.
+ *
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
*/
- void acknowledgeFullBackupOrRestore(int token, boolean allow,
+ void acknowledgeFullBackupOrRestore(int token, boolean allow, in String password,
IFullBackupRestoreObserver observer);
/**
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index d8adc6c..960d7fb 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -38,6 +38,7 @@
import android.widget.FrameLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
+import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
/**
* Provides the glue to show AppWidget views. This class offers automatic animation
@@ -276,6 +277,11 @@
if (adapter instanceof BaseAdapter) {
BaseAdapter baseAdapter = (BaseAdapter) adapter;
baseAdapter.notifyDataSetChanged();
+ } else if (adapter == null && adapterView instanceof RemoteAdapterConnectionCallback) {
+ // If the adapter is null, it may mean that the RemoteViewsAapter has not yet
+ // connected to its associated service, and hence the adapter hasn't been set.
+ // In this case, we need to defer the notify call until it has been set.
+ ((RemoteAdapterConnectionCallback) adapterView).deferNotifyDataSetChanged();
}
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b993bd8..ca6f085 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1143,6 +1143,69 @@
}
}
+ /**
+ * Enable control of the Bluetooth Adapter for a single application.
+ *
+ * <p>Some applications need to use Bluetooth for short periods of time to
+ * transfer data but don't want all the associated implications like
+ * automatic connection to headsets etc.
+ *
+ * <p> Multiple applications can call this. This is reference counted and
+ * Bluetooth disabled only when no one else is using it. There will be no UI
+ * shown to the user while bluetooth is being enabled. Any user action will
+ * override this call. For example, if user wants Bluetooth on and the last
+ * user of this API wanted to disable Bluetooth, Bluetooth will not be
+ * turned off.
+ *
+ * <p> This API is only meant to be used by internal applications. Third
+ * party applications but use {@link #enable} and {@link #disable} APIs.
+ *
+ * <p> If this API returns true, it means the callback will be called.
+ * The callback will be called with the current state of Bluetooth.
+ * If the state is not what was requested, an internal error would be the
+ * reason.
+ *
+ * @param on True for on, false for off.
+ * @param callback The callback to notify changes to the state.
+ * @hide
+ */
+ public boolean changeApplicationBluetoothState(boolean on,
+ BluetoothStateChangeCallback callback) {
+ if (callback == null) return false;
+
+ try {
+ return mService.changeApplicationBluetoothState(on, new
+ StateChangeCallbackWrapper(callback), new Binder());
+ } catch (RemoteException e) {
+ Log.e(TAG, "changeBluetoothState", e);
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ public interface BluetoothStateChangeCallback {
+ public void onBluetoothStateChange(boolean on);
+ }
+
+ /**
+ * @hide
+ */
+ public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
+ private BluetoothStateChangeCallback mCallback;
+
+ StateChangeCallbackWrapper(BluetoothStateChangeCallback
+ callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onBluetoothStateChange(boolean on) {
+ mCallback.onBluetoothStateChange(on);
+ }
+ }
+
private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
for (int i = 0; i < addresses.length; i++) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index d9525a3..4cb8220 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -566,6 +566,54 @@
}
/**
+ * Get the Bluetooth alias of the remote device.
+ * <p>Alias is the locally modified name of a remote device.
+ *
+ * @return the Bluetooth alias, or null if no alias or there was a problem
+ * @hide
+ */
+ public String getAlias() {
+ try {
+ return sService.getRemoteAlias(mAddress);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
+
+ /**
+ * Set the Bluetooth alias of the remote device.
+ * <p>Alias is the locally modified name of a remote device.
+ * <p>This methoid overwrites the alias. The changed
+ * alias is saved in the local storage so that the change
+ * is preserved over power cycle.
+ *
+ * @return true on success, false on error
+ * @hide
+ */
+ public boolean setAlias(String alias) {
+ try {
+ return sService.setRemoteAlias(mAddress, alias);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ /**
+ * Get the Bluetooth alias of the remote device.
+ * If Alias is null, get the Bluetooth name instead.
+ * @see #getAlias()
+ * @see #getName()
+ *
+ * @return the Bluetooth alias, or null if no alias or there was a problem
+ * @hide
+ */
+ public String getAliasName() {
+ String name = getAlias();
+ if (name == null) {
+ name = getName();
+ }
+ return name;
+ }
+
+ /**
* Start the bonding (pairing) process with the remote device.
* <p>This is an asynchronous call, it will return immediately. Register
* for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 183772d..ddede9c 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
import android.bluetooth.IBluetoothHealthCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealthAppConfiguration;
@@ -52,6 +53,9 @@
byte[] readOutOfBandData();
int getAdapterConnectionState();
+ boolean changeApplicationBluetoothState(boolean on,
+ in IBluetoothStateChangeCallback callback, in
+ IBinder b);
boolean createBond(in String address);
boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
@@ -62,6 +66,8 @@
boolean setDeviceOutOfBandData(in String address, in byte[] hash, in byte[] randomizer);
String getRemoteName(in String address);
+ String getRemoteAlias(in String address);
+ boolean setRemoteAlias(in String address, in String name);
int getRemoteClass(in String address);
ParcelUuid[] getRemoteUuids(in String address);
boolean fetchRemoteUuids(in String address, in ParcelUuid uuid, in IBluetoothCallback callback);
diff --git a/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
new file mode 100644
index 0000000..feccdce
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * System private API for Bluetooth state change callback.
+ *
+ * {@hide}
+ */
+interface IBluetoothStateChangeCallback
+{
+ void onBluetoothStateChange(boolean on);
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 364821e..1e72092 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -532,7 +532,7 @@
try {
AssetFileDescriptor fd = provider.openAssetFile(uri, mode);
if(fd == null) {
- releaseProvider(provider);
+ // The provider will be released by the finally{} clause
return null;
}
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
@@ -596,7 +596,7 @@
try {
AssetFileDescriptor fd = provider.openTypedAssetFile(uri, mimeType, opts);
if (fd == null) {
- releaseProvider(provider);
+ // The provider will be released by the finally{} clause
return null;
}
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index cdda910..2a02446 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -129,7 +129,7 @@
/**
* Flag for {@link #bindService}: don't allow this binding to raise
* the target service's process to the foreground scheduling priority.
- * It will still be raised to the at least the same memory priority
+ * It will still be raised to at least the same memory priority
* as the client (so that its process will not be killable in any
* situation where the client is not killable), but for CPU scheduling
* purposes it may be left in the background. This only has an impact
@@ -138,6 +138,16 @@
*/
public static final int BIND_NOT_FOREGROUND = 0x0004;
+ /**
+ * Flag for {@link #bindService}: allow the process hosting the bound
+ * service to go through its normal memory management. It will be
+ * treated more like a running service, allowing the system to
+ * (temporarily) expunge the process if low on memory or for some other
+ * whim it may have.
+ * @hide
+ */
+ public static final int BIND_ALLOW_OOM_MANAGEMENT = 0x0008;
+
/** Return an AssetManager instance for your application's package. */
public abstract AssetManager getAssets();
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 4e70b74..368c33e 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -40,6 +40,8 @@
*
* <p>Most implementations should not derive directly from this class, but
* instead inherit from {@link AsyncTaskLoader}.</p>
+ * <p>For more information, see the <a
+ * href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> developer guide.</p>
*
* @param <D> The result returned when the load is complete
*/
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 2cb8a86..5be6ec1 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1691,12 +1691,28 @@
continue;
}
- // skip the sync if it isn't manual and auto sync or
- // background data usage is disabled
+ final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
+ syncAdapterInfo = mSyncAdapters.getServiceInfo(
+ SyncAdapterType.newKey(op.authority, op.account.type));
+
+ // only proceed if network is connected for requesting UID
+ final boolean uidNetworkConnected;
+ if (syncAdapterInfo != null) {
+ final NetworkInfo networkInfo = getConnectivityManager()
+ .getActiveNetworkInfoForUid(syncAdapterInfo.uid);
+ uidNetworkConnected = networkInfo != null && networkInfo.isConnected();
+ } else {
+ uidNetworkConnected = false;
+ }
+
+ // skip the sync if it isn't manual, and auto sync or
+ // background data usage is disabled or network is
+ // disconnected for the target UID.
if (!op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
&& (syncableState > 0)
&& (!masterSyncAutomatically
|| !backgroundDataUsageAllowed
+ || !uidNetworkConnected
|| !mSyncStorageEngine.getSyncAutomatically(
op.account, op.authority))) {
operationIterator.remove();
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index d4e5cc1..b32664e 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -45,16 +45,23 @@
* {@link #toChars} or {@link #toCharsString()}.
*/
public Signature(String text) {
- final int N = text.length()/2;
- byte[] sig = new byte[N];
- for (int i=0; i<N; i++) {
- char c = text.charAt(i*2);
- byte b = (byte)(
- (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4);
- c = text.charAt(i*2 + 1);
- b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0'));
- sig[i] = b;
+ final byte[] input = text.getBytes();
+ final int N = input.length;
+ final byte[] sig = new byte[N / 2];
+ int sigIndex = 0;
+
+ for (int i = 0; i < N;) {
+ int b;
+
+ final int hi = input[i++];
+ b = (hi >= 'a' ? (hi - 'a' + 10) : (hi - '0')) << 4;
+
+ final int lo = input[i++];
+ b |= (lo >= 'a' ? (lo - 'a' + 10) : (lo - '0')) & 0x0F;
+
+ sig[sigIndex++] = (byte) (b & 0xFF);
}
+
mSignature = sig;
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index a168260..b487764 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -19,6 +19,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.graphics.ImageFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Handler;
@@ -35,6 +36,7 @@
import java.util.List;
import java.util.StringTokenizer;
+
/**
* The Camera class is used to set image capture settings, start/stop preview,
* snap pictures, and retrieve frames for encoding for video. This class is a
@@ -128,7 +130,9 @@
private static final int CAMERA_MSG_POSTVIEW_FRAME = 0x040;
private static final int CAMERA_MSG_RAW_IMAGE = 0x080;
private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
- private static final int CAMERA_MSG_ALL_MSGS = 0x1FF;
+ private static final int CAMERA_MSG_RAW_IMAGE_NOTIFY = 0x200;
+ private static final int CAMERA_MSG_METADATA_FACE = 0x400;
+ private static final int CAMERA_MSG_ALL_MSGS = 0x4FF;
private int mNativeContext; // accessed by native methods
private EventHandler mEventHandler;
@@ -139,9 +143,11 @@
private PictureCallback mPostviewCallback;
private AutoFocusCallback mAutoFocusCallback;
private OnZoomChangeListener mZoomListener;
+ private FaceDetectionListener mFaceListener;
private ErrorCallback mErrorCallback;
private boolean mOneShot;
private boolean mWithBuffer;
+ private boolean mFaceDetectionRunning = false;
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -160,6 +166,25 @@
public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO";
/**
+ * Hardware face detection. It does not use much CPU.
+ *
+ * @see #startFaceDetection(int)
+ * @see Parameters#getMaxNumDetectedFaces(int)
+ * @see #CAMERA_FACE_DETECTION_SW
+ * @hide
+ */
+ public static final int CAMERA_FACE_DETECTION_HW = 0;
+
+ /**
+ * Software face detection. It uses some CPU. Applications must use
+ * {@link #setPreviewTexture(SurfaceTexture)} for preview in this mode.
+ *
+ * @see #CAMERA_FACE_DETECTION_HW
+ * @hide
+ */
+ public static final int CAMERA_FACE_DETECTION_SW = 1;
+
+ /**
* Returns the number of physical cameras available on this device.
*/
public native static int getNumberOfCameras();
@@ -295,6 +320,7 @@
*/
public final void release() {
native_release();
+ mFaceDetectionRunning = false;
}
/**
@@ -460,7 +486,12 @@
* Stops capturing and drawing preview frames to the surface, and
* resets the camera for a future call to {@link #startPreview()}.
*/
- public native final void stopPreview();
+ public final void stopPreview() {
+ _stopPreview();
+ mFaceDetectionRunning = false;
+ }
+
+ private native final void _stopPreview();
/**
* Return current preview state.
@@ -690,6 +721,12 @@
}
return;
+ case CAMERA_MSG_METADATA_FACE:
+ if (mFaceListener != null) {
+ mFaceListener.onFaceDetection((Face[])msg.obj, mCamera);
+ }
+ return;
+
case CAMERA_MSG_ERROR :
Log.e(TAG, "Error " + msg.arg1);
if (mErrorCallback != null) {
@@ -1031,6 +1068,143 @@
mZoomListener = listener;
}
+ /**
+ * Callback interface for face detected in the preview frame.
+ *
+ * @hide
+ */
+ public interface FaceDetectionListener
+ {
+ /**
+ * Notify the listener of the detected faces in the preview frame.
+ *
+ * @param faces the detected faces. The list is sorted by the score.
+ * The highest score is the first element.
+ * @param camera the Camera service object
+ */
+ void onFaceDetection(Face[] faces, Camera camera);
+ }
+
+ /**
+ * Registers a listener to be notified about the face detected of the
+ * preview frame.
+ *
+ * @param listener the listener to notify
+ * @see #startFaceDetection(int)
+ * @hide
+ */
+ public final void setFaceDetectionListener(FaceDetectionListener listener)
+ {
+ mFaceListener = listener;
+ }
+
+ /**
+ * Start the face detection. This should be called after preview is started.
+ * The camera will notify {@link FaceDetectionListener} of the detected
+ * faces in the preview frame. The detected faces may be the same as the
+ * previous ones. Applications should call {@link #stopFaceDetection} to
+ * stop the face detection. This method is supported if {@link
+ * Parameters#getMaxNumDetectedFaces(int)} returns a number larger than 0.
+ * Hardware and software face detection cannot be used at the same time.
+ * If the face detection has started, apps should not call this again.
+ *
+ * In hardware face detection mode, {@link Parameters#setWhiteBalance(String)},
+ * {@link Parameters#setFocusAreas(List)}, and {@link Parameters#setMeteringAreas(List)}
+ * have no effect.
+ *
+ * @param type face detection type. This can be either {@link
+ * #CAMERA_FACE_DETECTION_HW} or {@link #CAMERA_FACE_DETECTION_SW}
+ * @throws IllegalArgumentException if the face detection type is
+ * unsupported or invalid.
+ * @throws RuntimeException if the method fails or the face detection is
+ * already running.
+ * @see #CAMERA_FACE_DETECTION_HW
+ * @see #CAMERA_FACE_DETECTION_SW
+ * @see FaceDetectionListener
+ * @see #stopFaceDetection()
+ * @see Parameters#getMaxNumDetectedFaces(int)
+ * @hide
+ */
+ public final void startFaceDetection(int type) {
+ if (type != CAMERA_FACE_DETECTION_HW && type != CAMERA_FACE_DETECTION_SW) {
+ throw new IllegalArgumentException("Invalid face detection type " + type);
+ }
+ if (mFaceDetectionRunning) {
+ throw new RuntimeException("Face detection is already running");
+ }
+ _startFaceDetection(type);
+ mFaceDetectionRunning = true;
+ }
+
+ /**
+ * Stop the face detection.
+ *
+ * @see #startFaceDetection(int)
+ * @hide
+ */
+ public final void stopFaceDetection() {
+ _stopFaceDetection();
+ mFaceDetectionRunning = false;
+ }
+
+ private native final void _startFaceDetection(int type);
+ private native final void _stopFaceDetection();
+
+ /**
+ * The information of a face from camera face detection.
+ *
+ * @hide
+ */
+ public static class Face {
+ /**
+ * Bounds of the face. (-1000, -1000) represents the top-left of the
+ * camera field of view, and (1000, 1000) represents the bottom-right of
+ * the field of view. The width and height cannot be 0 or negative. This
+ * is supported by both hardware and software face detection.
+ *
+ * <p>The direction is relative to the sensor orientation, that is, what
+ * the sensor sees. The direction is not affected by the rotation or
+ * mirroring of {@link #setDisplayOrientation(int)}.</p>
+ *
+ * @see #startFaceDetection(int)
+ */
+ Rect rect;
+
+ /**
+ * The confidence level of the face. The range is 1 to 100. 100 is the
+ * highest confidence. This is supported by both hardware and software
+ * face detction.
+ *
+ * @see #startFaceDetection(int)
+ */
+ int score;
+
+ /**
+ * An unique id per face while the face is visible to the tracker. If
+ * the face leaves the field-of-view and comes back, it will get a new
+ * id. If the value is 0, id is not supported.
+ */
+ int id;
+
+ /**
+ * The coordinates of the center of the left eye. The range is -1000 to
+ * 1000. null if this is not supported.
+ */
+ Point leftEye;
+
+ /**
+ * The coordinates of the center of the right eye. The range is -1000 to
+ * 1000. null if this is not supported.
+ */
+ Point rightEye;
+
+ /**
+ * The coordinates of the center of the mouth. The range is -1000 to
+ * 1000. null if this is not supported.
+ */
+ Point mouth;
+ }
+
// Error codes match the enum in include/ui/Camera.h
/**
@@ -1295,6 +1469,8 @@
private static final String KEY_VIDEO_SIZE = "video-size";
private static final String KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO =
"preferred-preview-size-for-video";
+ private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw";
+ private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -2977,6 +3153,25 @@
set(KEY_METERING_AREAS, meteringAreas);
}
+ /**
+ * Gets the maximum number of detected faces supported. This is the
+ * maximum length of the list returned from {@link FaceDetectionListener}.
+ * If the return value is 0, face detection of the specified type is not
+ * supported.
+ *
+ * @return the maximum number of detected face supported by the camera.
+ * @see #startFaceDetection(int)
+ * @hide
+ */
+ public int getMaxNumDetectedFaces(int type) {
+ if (type == CAMERA_FACE_DETECTION_HW) {
+ return getInt(KEY_MAX_NUM_DETECTED_FACES_HW, 0);
+ } else if (type == CAMERA_FACE_DETECTION_SW){
+ return getInt(KEY_MAX_NUM_DETECTED_FACES_SW, 0);
+ }
+ throw new IllegalArgumentException("Invalid face detection type " + type);
+ }
+
// Splits a comma delimited string to an ArrayList of String.
// Return null if the passing string is null or the size is 0.
private ArrayList<String> split(String str) {
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 82495e3..3e07b0a 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -18,6 +18,7 @@
import android.net.INetworkPolicyListener;
import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
/**
* Interface that creates and modifies network policy rules.
@@ -37,4 +38,9 @@
void setNetworkPolicies(in NetworkPolicy[] policies);
NetworkPolicy[] getNetworkPolicies();
+ void snoozePolicy(in NetworkTemplate template);
+
+ void setRestrictBackground(boolean restrictBackground);
+ boolean getRestrictBackground();
+
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 52cab30..aaad8a1 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -21,6 +21,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.Objects;
+
/**
* Policy for networks matching a {@link NetworkTemplate}, including usage cycle
* and limits to be enforced.
@@ -30,20 +32,21 @@
public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
public static final long WARNING_DISABLED = -1;
public static final long LIMIT_DISABLED = -1;
+ public static final long SNOOZE_NEVER = -1;
public final NetworkTemplate template;
public int cycleDay;
public long warningBytes;
public long limitBytes;
+ public long lastSnooze;
- // TODO: teach how to snooze limit for current cycle
-
- public NetworkPolicy(
- NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes) {
+ public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes,
+ long lastSnooze) {
this.template = checkNotNull(template, "missing NetworkTemplate");
this.cycleDay = cycleDay;
this.warningBytes = warningBytes;
this.limitBytes = limitBytes;
+ this.lastSnooze = lastSnooze;
}
public NetworkPolicy(Parcel in) {
@@ -51,6 +54,7 @@
cycleDay = in.readInt();
warningBytes = in.readLong();
limitBytes = in.readLong();
+ lastSnooze = in.readLong();
}
/** {@inheritDoc} */
@@ -59,6 +63,7 @@
dest.writeInt(cycleDay);
dest.writeLong(warningBytes);
dest.writeLong(limitBytes);
+ dest.writeLong(lastSnooze);
}
/** {@inheritDoc} */
@@ -80,9 +85,25 @@
}
@Override
+ public int hashCode() {
+ return Objects.hashCode(template, cycleDay, warningBytes, limitBytes, lastSnooze);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof NetworkPolicy) {
+ final NetworkPolicy other = (NetworkPolicy) obj;
+ return Objects.equal(template, other.template) && cycleDay == other.cycleDay
+ && warningBytes == other.warningBytes && limitBytes == other.limitBytes
+ && lastSnooze == other.lastSnooze;
+ }
+ return false;
+ }
+
+ @Override
public String toString() {
return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes="
- + warningBytes + ", limitBytes=" + limitBytes;
+ + warningBytes + ", limitBytes=" + limitBytes + ", lastSnooze=" + lastSnooze;
}
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 593b2b7..1e9d813 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -52,26 +52,10 @@
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
/**
- * {@link Intent} action launched when user selects {@link NetworkPolicy}
- * warning notification.
+ * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
+ * applies to.
*/
- public static final String ACTION_DATA_USAGE_WARNING =
- "android.intent.action.DATA_USAGE_WARNING";
-
- /**
- * {@link Intent} action launched when user selects {@link NetworkPolicy}
- * limit notification.
- */
- public static final String ACTION_DATA_USAGE_LIMIT =
- "android.intent.action.DATA_USAGE_LIMIT";
-
- /**
- * {@link Intent} extra included in {@link #ACTION_DATA_USAGE_WARNING} and
- * {@link #ACTION_DATA_USAGE_LIMIT} to indicate which
- * {@link NetworkTemplate} rule it applies to.
- */
- public static final String EXTRA_NETWORK_TEMPLATE =
- "android.intent.extra.NETWORK_TEMPLATE";
+ public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
private INetworkPolicyManager mService;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 76534ef..e289fc1 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -20,6 +20,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
+import java.util.Collection;
import android.util.Log;
@@ -235,4 +236,18 @@
throw new IllegalArgumentException(e);
}
}
+
+ /**
+ * Create a string array of host addresses from a collection of InetAddresses
+ * @param addrs a Collection of InetAddresses
+ * @return an array of Strings containing their host addresses
+ */
+ public static String[] makeStrings(Collection<InetAddress> addrs) {
+ String[] result = new String[addrs.size()];
+ int i = 0;
+ for (InetAddress addr : addrs) {
+ result[i++] = addr.getHostAddress();
+ }
+ return result;
+ }
}
diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java
index 4582523..25cedb6 100644
--- a/core/java/android/net/VpnBuilder.java
+++ b/core/java/android/net/VpnBuilder.java
@@ -91,7 +91,6 @@
*
* <p class="note">Using this class requires
* {@link android.Manifest.permission#VPN} permission.
- * @hide
*/
public class VpnBuilder {
diff --git a/core/java/android/net/http/SslError.java b/core/java/android/net/http/SslError.java
index 1e1cb49..08c6692 100644
--- a/core/java/android/net/http/SslError.java
+++ b/core/java/android/net/http/SslError.java
@@ -30,7 +30,7 @@
/**
* The certificate is not yet valid
*/
- public static final int SSL_NOTYETVALID = 0;
+ public static final int SSL_NOTYETVALID = 0;
/**
* The certificate has expired
*/
@@ -43,12 +43,23 @@
* The certificate authority is not trusted
*/
public static final int SSL_UNTRUSTED = 3;
+ /**
+ * The date of the certificate is invalid
+ */
+ public static final int SSL_DATE_INVALID = 4;
+ /**
+ * The certificate is invalid
+ */
+ public static final int SSL_INVALID = 5;
/**
* The number of different SSL errors (update if you add a new SSL error!!!)
+ * @deprecated This constant is not necessary for using the SslError API and
+ * can change from release to release.
*/
- public static final int SSL_MAX_ERROR = 4;
+ @Deprecated
+ public static final int SSL_MAX_ERROR = 6;
/**
* The SSL error set bitfield (each individual error is an bit index;
@@ -117,6 +128,30 @@
}
/**
+ * Creates an SslError object from a chromium error code.
+ * @param error The chromium error code
+ * @param certificate The associated SSL certificate
+ * @param url The associated URL.
+ * @hide chromium error codes only available inside the framework
+ */
+ public static SslError SslErrorFromChromiumErrorCode(
+ int error, SslCertificate cert, String url) {
+ // The chromium error codes are in:
+ // external/chromium/net/base/net_error_list.h
+ if (error > -200 || error < -299) {
+ throw new NullPointerException("Not a valid chromium SSL error code.");
+ }
+ if (error == -200)
+ return new SslError(SSL_IDMISMATCH, cert, url);
+ if (error == -201)
+ return new SslError(SSL_DATE_INVALID, cert, url);
+ if (error == -202)
+ return new SslError(SSL_UNTRUSTED, cert, url);
+ // Map all other errors to SSL_INVALID
+ return new SslError(SSL_INVALID, cert, url);
+ }
+
+ /**
* Creates a new SSL error set object
* @param error The SSL error
* @param certificate The associated SSL certificate
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 1174e3b..3704248 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -212,7 +212,7 @@
/**
* Set quota for an interface.
*/
- void setInterfaceQuota(String iface, long quota);
+ void setInterfaceQuota(String iface, long quotaBytes);
/**
* Remove quota for an interface.
@@ -220,6 +220,21 @@
void removeInterfaceQuota(String iface);
/**
+ * Set alert for an interface; requires that iface already has quota.
+ */
+ void setInterfaceAlert(String iface, long alertBytes);
+
+ /**
+ * Remove alert for an interface.
+ */
+ void removeInterfaceAlert(String iface);
+
+ /**
+ * Set alert across all interfaces.
+ */
+ void setGlobalAlert(long alertBytes);
+
+ /**
* Control network activity of a UID over interfaces with a quota limit.
*/
void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces);
@@ -252,12 +267,12 @@
void setDnsServersForInterface(String iface, in String[] servers);
/**
- * Flush the DNS cache associated with the default interface
+ * Flush the DNS cache associated with the default interface.
*/
void flushDefaultDnsCache();
/**
- * Flush the DNS cache associated with the specified interface
+ * Flush the DNS cache associated with the specified interface.
*/
void flushInterfaceDnsCache(String iface);
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 0067e940..9a53d76 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -20,12 +20,15 @@
import android.os.WorkSource;
/** @hide */
+
interface IPowerManager
{
+ // WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
void goToSleep(long time);
void goToSleepWithReason(long time, int reason);
+ // WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
void releaseWakeLock(IBinder lock, int flags);
void userActivity(long when, boolean noChangeLights);
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index 55ef108..b6f00ad 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -202,7 +202,8 @@
&& view.isEnabled()) {
mSendAccessibilityEventViewClickedType = false;
if (mSendAccessibilityEventTypeViewClicked == null) {
- mSendAccessibilityEventTypeViewClicked = new SendAccessibilityEventTypeViewClicked();
+ mSendAccessibilityEventTypeViewClicked =
+ new SendAccessibilityEventTypeViewClicked();
}
mSendAccessibilityEventTypeViewClicked.mView = view;
view.post(mSendAccessibilityEventTypeViewClicked);
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 382fcf3..b8ef7be 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -184,6 +184,15 @@
public static final String VOICEMAIL_URI = "voicemail_uri";
/**
+ * Whether this item has been read or otherwise consumed by the user.
+ * <p>
+ * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
+ * existence of the entry, this implies the user has interacted with the entry.
+ * <P>Type: INTEGER (boolean)</P>
+ */
+ public static final String IS_READ = "is_read";
+
+ /**
* Adds a call to the call log.
*
* @param ci the CallerInfo object to get the target contact from. Can be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index a0f1eec..5765dde 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1973,6 +1973,16 @@
public static final String DATA_SET = "data_set";
/**
+ * A concatenation of the account type and data set (delimited by a forward
+ * slash) - if the data set is empty, this will be the same as the account
+ * type. For applications that need to be aware of the data set, this can
+ * be used instead of account type to distinguish sets of data. This is
+ * never intended to be used for specifying accounts.
+ * @hide
+ */
+ public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
+
+ /**
* The aggregation mode for this contact.
* <P>Type: INTEGER</P>
*/
@@ -6444,6 +6454,16 @@
public static final String DATA_SET = "data_set";
/**
+ * A concatenation of the account type and data set (delimited by a forward
+ * slash) - if the data set is empty, this will be the same as the account
+ * type. For applications that need to be aware of the data set, this can
+ * be used instead of account type to distinguish sets of data. This is
+ * never intended to be used for specifying accounts.
+ * @hide
+ */
+ public static final String ACCOUNT_TYPE_AND_DATA_SET = "account_type_and_data_set";
+
+ /**
* The display title of this group.
* <p>
* Type: TEXT
@@ -7413,6 +7433,16 @@
"com.android.contacts.action.ATTACH_IMAGE";
/**
+ * This is the intent that is fired when the user clicks the "invite to the network" button
+ * on a contact. Only sent to an activity which is explicitly registered by a contact
+ * provider which supports the "invite to the network" feature.
+ * <p>
+ * {@link Intent#getData()} contains the lookup URI for the contact.
+ */
+ public static final String INVITE_CONTACT =
+ "com.android.contacts.action.INVITE_CONTACT";
+
+ /**
* Takes as input a data URI with a mailto: or tel: scheme. If a single
* contact exists with the given data it will be shown. If no contact
* exists, a dialog will ask the user if they want to create a new
@@ -7861,6 +7891,19 @@
* @hide
*/
public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
+
+ /**
+ * Used to specify the data set within the account in which to create the
+ * new contact.
+ * <p>
+ * This value is optional - if it is not specified, the contact will be
+ * created in the base account, with no data set.
+ * <p>
+ * Type: String
+ *
+ * @hide
+ */
+ public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
}
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1cd46de..d3ff8f8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -549,6 +549,20 @@
public static final String ACTION_DEVICE_INFO_SETTINGS =
"android.settings.DEVICE_INFO_SETTINGS";
+ /**
+ * Activity Action: Show NFC sharing settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NFCSHARING_SETTINGS =
+ "android.settings.NFCSHARING_SETTINGS";
+
// End of Intent actions for Settings
/**
@@ -2688,11 +2702,9 @@
public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
/**
- * If touch exploration is requested. Touch exploration is enabled if it is
- * requested by this setting, accessibility is enabled and there is at least
- * one enabled accessibility serivce that provides spoken feedback.
+ * If touch exploration is enabled.
*/
- public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
+ public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
/**
* List of the enabled accessibility providers.
@@ -3030,13 +3042,6 @@
"wifi_watchdog_walled_garden_url";
/**
- * The pattern string in the fetched URL used to detect a walled garden
- * @hide
- */
- public static final String WIFI_WATCHDOG_WALLED_GARDEN_PATTERN =
- "wifi_watchdog_walled_garden_pattern";
-
- /**
* Boolean to determine whether to notify on disabling a network. Secure setting used
* to notify user only once. This setting is not monitored continuously.
* @hide
@@ -3935,6 +3940,10 @@
/** Timeout in milliseconds to wait for NTP server. {@hide} */
public static final String NTP_TIMEOUT = "ntp_timeout";
+ /** Autofill server address (Used in WebView/browser). {@hide} */
+ public static final String WEB_AUTOFILL_QUERY_URL =
+ "web_autofill_query_url";
+
/**
* @hide
*/
@@ -3948,6 +3957,7 @@
ACCESSIBILITY_SCRIPT_INJECTION,
BACKUP_AUTO_RESTORE,
ENABLED_ACCESSIBILITY_SERVICES,
+ TOUCH_EXPLORATION_ENABLED,
TTS_USE_DEFAULTS,
TTS_DEFAULT_RATE,
TTS_DEFAULT_PITCH,
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 2ad7395..a31374f 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -123,10 +123,10 @@
*/
public static final String DURATION = Calls.DURATION;
/**
- * Whether this is a new voicemail (i.e. has not been heard).
+ * Whether this item has been read or otherwise consumed by the user.
* <P>Type: INTEGER (boolean)</P>
*/
- public static final String NEW = Calls.NEW;
+ public static final String IS_READ = Calls.IS_READ;
/**
* The mail box state of the voicemail. This field is currently not used by the system.
* <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED},
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
new file mode 100644
index 0000000..83f5a9f
--- /dev/null
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -0,0 +1,653 @@
+/*
+ * 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.IBluetoothStateChangeCallback;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.util.IState;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import java.io.PrintWriter;
+
+/**
+ * Bluetooth Adapter StateMachine
+ * All the states are at the same level, ie, no hierarchy.
+ * (BluetootOn)<----------------------<-
+ * | ^ -------------------->- |
+ * | | | |
+ * TURN_OFF | | BECAME_PAIRABLE m1 | | USER_TURN_ON
+ * AIRPLANE_MODE_ON | | | |
+ * V | | |
+ * (Switching) (PerProcessState)
+ * | ^ | |
+ * BECAME_NON_PAIRABLE& | | TURN_ON(_CONTINUE) | |
+ * ALL_DEVICES_DISCONNECTED | | m2 | |
+ * V |------------------------< | BECAME_PAIRABLE
+ * (HotOff)---------------------------- PER_PROCESS_TURN_ON
+ * / ^
+ * / | SERVICE_RECORD_LOADED
+ * | |
+ * TURN_COLD | (Warmup)
+ * \ ^
+ * \ | TURN_HOT/TURN_ON
+ * | | AIRPLANE_MODE_OFF(when Bluetooth was on before)
+ * V |
+ * (PowerOff) <----- initial state
+ *
+ * Legend:
+ * m1 = USER_TURN_OFF
+ * m2 = Transition to HotOff when number of process wanting BT on is 0.
+ * BECAME_NON_PAIRABLE will make the transition.
+ */
+final class BluetoothAdapterStateMachine extends StateMachine {
+ private static final String TAG = "BluetoothAdapterStateMachine";
+ private static final boolean DBG = false;
+
+ // Message(what) to take an action
+ //
+ // We get this message when user tries to turn on BT
+ static final int USER_TURN_ON = 1;
+ // We get this message when user tries to turn off BT
+ static final int USER_TURN_OFF = 2;
+
+ // Message(what) to report a event that the state machine need to respond to
+ //
+ // Event indicates sevice records have been loaded
+ static final int SERVICE_RECORD_LOADED = 51;
+ // Event indicates all the remote Bluetooth devices has been disconnected
+ static final int ALL_DEVICES_DISCONNECTED = 52;
+ // Event indicates the Bluetooth is connectable
+ static final int BECAME_PAIRABLE = 53;
+ // Event indicates the Bluetooth is non-connectable.
+ static final int BECAME_NON_PAIRABLE = 54;
+ // Event indicates airplane mode is turned on
+ static final int AIRPLANE_MODE_ON = 55;
+ // Event indicates airplane mode is turned off
+ static final int AIRPLANE_MODE_OFF = 56;
+
+ // private internal messages
+ //
+ // Turn on Bluetooth Module, Load firmware, and do all the preparation
+ // needed to get the Bluetooth Module ready but keep it not discoverable
+ // and not connectable. This way the Bluetooth Module can be quickly
+ // switched on if needed
+ private static final int TURN_HOT = 101;
+ // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
+ // state change intent so that we will not broadcast the intent again in
+ // other state
+ private static final int TURN_ON_CONTINUE = 102;
+ // Unload firmware, turning off Bluetooth module power
+ private static final int TURN_COLD = 103;
+ // Per process enable / disable messages
+ static final int PER_PROCESS_TURN_ON = 104;
+ static final int PER_PROCESS_TURN_OFF = 105;
+
+ private Context mContext;
+ private BluetoothService mBluetoothService;
+ private BluetoothEventLoop mEventLoop;
+
+ private BluetoothOn mBluetoothOn;
+ private Switching mSwitching;
+ private HotOff mHotOff;
+ private WarmUp mWarmUp;
+ private PowerOff mPowerOff;
+ private PerProcessState mPerProcessState;
+
+ // this is the BluetoothAdapter state that reported externally
+ private int mPublicState;
+
+ BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
+ BluetoothAdapter bluetoothAdapter) {
+ super(TAG);
+ mContext = context;
+ mBluetoothService = bluetoothService;
+ mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this);
+
+ mBluetoothOn = new BluetoothOn();
+ mSwitching = new Switching();
+ mHotOff = new HotOff();
+ mWarmUp = new WarmUp();
+ mPowerOff = new PowerOff();
+ mPerProcessState = new PerProcessState();
+
+ addState(mBluetoothOn);
+ addState(mSwitching);
+ addState(mHotOff);
+ addState(mWarmUp);
+ addState(mPowerOff);
+ addState(mPerProcessState);
+
+ setInitialState(mPowerOff);
+ mPublicState = BluetoothAdapter.STATE_OFF;
+
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ sendMessage(TURN_HOT);
+ }
+ }
+
+ /**
+ * Bluetooth module's power is off, firmware is not loaded.
+ */
+ private class PowerOff extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Enter PowerOff: ");
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("PowerOff process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_ON:
+ // starts turning on BT module, broadcast this out
+ transitionTo(mWarmUp);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ if (prepareBluetooth()) {
+ // this is user request, save the setting
+ if ((Boolean) message.obj) {
+ persistSwitchSetting(true);
+ }
+ // We will continue turn the BT on all the way to the BluetoothOn state
+ deferMessage(obtainMessage(TURN_ON_CONTINUE));
+ } else {
+ Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+ transitionTo(mPowerOff);
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ }
+ break;
+ case TURN_HOT:
+ if (prepareBluetooth()) {
+ transitionTo(mWarmUp);
+ }
+ break;
+ case AIRPLANE_MODE_OFF:
+ if (getBluetoothPersistedSetting()) {
+ // starts turning on BT module, broadcast this out
+ transitionTo(mWarmUp);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ if (prepareBluetooth()) {
+ // We will continue turn the BT on all the way to the BluetoothOn state
+ deferMessage(obtainMessage(TURN_ON_CONTINUE));
+ transitionTo(mWarmUp);
+ } else {
+ Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+ transitionTo(mPowerOff);
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ }
+ } else if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ sendMessage(TURN_HOT);
+ }
+ break;
+ case PER_PROCESS_TURN_ON:
+ if (prepareBluetooth()) {
+ transitionTo(mWarmUp);
+ }
+ deferMessage(obtainMessage(PER_PROCESS_TURN_ON));
+ break;
+ case PER_PROCESS_TURN_OFF:
+ perProcessCallback(false, (IBluetoothStateChangeCallback) message.obj);
+ break;
+ case AIRPLANE_MODE_ON:
+ case USER_TURN_OFF: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ /**
+ * Turn on Bluetooth Module, Load firmware, and do all the preparation
+ * needed to get the Bluetooth Module ready but keep it not discoverable
+ * and not connectable.
+ * The last step of this method sets up the local service record DB.
+ * There will be a event reporting the status of the SDP setup.
+ */
+ private boolean prepareBluetooth() {
+ if (mBluetoothService.enableNative() != 0) {
+ return false;
+ }
+
+ // try to start event loop, give 2 attempts
+ int retryCount = 2;
+ boolean eventLoopStarted = false;
+ while ((retryCount-- > 0) && !eventLoopStarted) {
+ mEventLoop.start();
+ // it may take a moment for the other thread to do its
+ // thing. Check periodically for a while.
+ int pollCount = 5;
+ while ((pollCount-- > 0) && !eventLoopStarted) {
+ if (mEventLoop.isEventLoopRunning()) {
+ eventLoopStarted = true;
+ break;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ }
+
+ if (!eventLoopStarted) {
+ mBluetoothService.disableNative();
+ return false;
+ }
+
+ // get BluetoothService ready
+ if (!mBluetoothService.prepareBluetooth()) {
+ mEventLoop.stop();
+ mBluetoothService.disableNative();
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Turning on Bluetooth module's power, loading firmware, starting
+ * event loop thread to listen on Bluetooth module event changes.
+ */
+ private class WarmUp extends State {
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter WarmUp");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("WarmUp process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case SERVICE_RECORD_LOADED:
+ transitionTo(mHotOff);
+ break;
+ case USER_TURN_ON: // handle this at HotOff state
+ case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
+ // on to the BluetoothOn state
+ case AIRPLANE_MODE_ON:
+ case AIRPLANE_MODE_OFF:
+ case PER_PROCESS_TURN_ON:
+ case PER_PROCESS_TURN_OFF:
+ deferMessage(message);
+ break;
+ case USER_TURN_OFF: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+ /**
+ * Bluetooth Module has powered, firmware loaded, event loop started,
+ * SDP loaded, but the modules stays non-discoverable and
+ * non-connectable.
+ */
+ private class HotOff extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Enter HotOff:");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("HotOff process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_ON:
+ if ((Boolean) message.obj) {
+ persistSwitchSetting(true);
+ }
+ // let it fall to TURN_ON_CONTINUE:
+ //$FALL-THROUGH$
+ case TURN_ON_CONTINUE:
+ mBluetoothService.switchConnectable(true);
+ transitionTo(mSwitching);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ break;
+ case AIRPLANE_MODE_ON:
+ case TURN_COLD:
+ mBluetoothService.shutoffBluetooth();
+ mEventLoop.stop();
+ transitionTo(mPowerOff);
+ // ASSERT no support of config_bluetooth_adapter_quick_switch
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ break;
+ case AIRPLANE_MODE_OFF:
+ if (getBluetoothPersistedSetting()) {
+ transitionTo(mSwitching);
+ mBluetoothService.switchConnectable(true);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ }
+ break;
+ case USER_TURN_OFF: // ignore
+ break;
+ case PER_PROCESS_TURN_ON:
+ transitionTo(mPerProcessState);
+
+ // Resend the PER_PROCESS_TURN_ON message so that the callback
+ // can be sent through.
+ deferMessage(message);
+
+ mBluetoothService.switchConnectable(true);
+ break;
+ case PER_PROCESS_TURN_OFF:
+ perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+ private class Switching extends State {
+
+ @Override
+ public void enter() {
+ int what = getCurrentMessage().what;
+ if (DBG) log("Enter Switching: " + what);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("Switching process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case BECAME_PAIRABLE:
+ String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")};
+ mEventLoop.onPropertyChanged(propVal);
+
+ // run bluetooth now that it's turned on
+ mBluetoothService.runBluetooth();
+ transitionTo(mBluetoothOn);
+ broadcastState(BluetoothAdapter.STATE_ON);
+ break;
+ case BECAME_NON_PAIRABLE:
+ if (mBluetoothService.getAdapterConnectionState() ==
+ BluetoothAdapter.STATE_DISCONNECTED) {
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ }
+ break;
+ case ALL_DEVICES_DISCONNECTED:
+ if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) {
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ }
+ break;
+ case USER_TURN_ON:
+ case AIRPLANE_MODE_OFF:
+ case AIRPLANE_MODE_ON:
+ case PER_PROCESS_TURN_ON:
+ case PER_PROCESS_TURN_OFF:
+ case USER_TURN_OFF:
+ deferMessage(message);
+ break;
+
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ private void finishSwitchingOff() {
+ mBluetoothService.finishDisable();
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ } else {
+ deferMessage(obtainMessage(TURN_COLD));
+ }
+ }
+ }
+
+ private class BluetoothOn extends State {
+ private boolean mPersistBluetoothOff = false;
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter BluetoothOn: " + mPersistBluetoothOff);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("BluetoothOn process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_OFF:
+ if ((Boolean) message.obj) {
+ persistSwitchSetting(false);
+ }
+
+ if (mBluetoothService.isDiscovering()) {
+ mBluetoothService.cancelDiscovery();
+ }
+ if (!mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
+ transitionTo(mPerProcessState);
+ deferMessage(obtainMessage(USER_TURN_OFF));
+ break;
+ }
+ //$FALL-THROUGH$ to AIRPLANE_MODE_ON
+ case AIRPLANE_MODE_ON:
+ transitionTo(mSwitching);
+ broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+ mBluetoothService.switchConnectable(false);
+ mBluetoothService.disconnectDevices();
+
+ // we turn all the way to PowerOff with AIRPLANE_MODE_ON
+ if (message.what == AIRPLANE_MODE_ON) {
+ // We inform all the per process callbacks
+ allProcessesCallback(false);
+ deferMessage(obtainMessage(AIRPLANE_MODE_ON));
+ }
+ break;
+ case AIRPLANE_MODE_OFF: // ignore
+ case USER_TURN_ON: // ignore
+ break;
+ case PER_PROCESS_TURN_ON:
+ perProcessCallback(true, (IBluetoothStateChangeCallback)message.obj);
+ break;
+ case PER_PROCESS_TURN_OFF:
+ perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+
+ private class PerProcessState extends State {
+ IBluetoothStateChangeCallback mCallback = null;
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter PerProcessState");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("PerProcessState process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch (message.what) {
+ case PER_PROCESS_TURN_ON:
+ mCallback = (IBluetoothStateChangeCallback)getCurrentMessage().obj;
+
+ // If this is not the first application call the callback.
+ if (mBluetoothService.getNumberOfApplicationStateChangeTrackers() > 1) {
+ perProcessCallback(true, mCallback);
+ }
+ break;
+ case BECAME_PAIRABLE:
+ perProcessCallback(true, mCallback);
+ break;
+ case USER_TURN_ON:
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ persistSwitchSetting(true);
+
+ String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")};
+ mEventLoop.onPropertyChanged(propVal);
+
+ // run bluetooth now that it's turned on
+ mBluetoothService.runBluetooth();
+ transitionTo(mBluetoothOn);
+ broadcastState(BluetoothAdapter.STATE_ON);
+ break;
+ case USER_TURN_OFF:
+ broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+ if (mBluetoothService.getAdapterConnectionState() !=
+ BluetoothAdapter.STATE_DISCONNECTED) {
+ mBluetoothService.disconnectDevices();
+ break;
+ }
+ //$FALL-THROUGH$ all devices are already disconnected
+ case ALL_DEVICES_DISCONNECTED:
+ mBluetoothService.finishDisable();
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ break;
+ case PER_PROCESS_TURN_OFF:
+ perProcessCallback(false, (IBluetoothStateChangeCallback)message.obj);
+ if (mBluetoothService.isApplicationStateChangeTrackerEmpty()) {
+ mBluetoothService.switchConnectable(false);
+ }
+ break;
+ case BECAME_NON_PAIRABLE:
+ transitionTo(mHotOff);
+ if (!mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ deferMessage(obtainMessage(TURN_COLD));
+ }
+ break;
+ case AIRPLANE_MODE_ON:
+ mBluetoothService.switchConnectable(false);
+ allProcessesCallback(false);
+ // we turn all the way to PowerOff with AIRPLANE_MODE_ON
+ deferMessage(obtainMessage(AIRPLANE_MODE_ON));
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+ }
+
+
+ private void perProcessCallback(boolean on, IBluetoothStateChangeCallback c) {
+ if (c == null) return;
+
+ try {
+ c.onBluetoothStateChange(on);
+ } catch (RemoteException e) {}
+ }
+
+ private void allProcessesCallback(boolean on) {
+ for (IBluetoothStateChangeCallback c:
+ mBluetoothService.getApplicationStateChangeCallbacks()) {
+ perProcessCallback(on, c);
+ }
+ if (!on) {
+ mBluetoothService.clearApplicationStateChangeTracker();
+ }
+ }
+
+ /**
+ * Return the public BluetoothAdapter state
+ */
+ int getBluetoothAdapterState() {
+ return mPublicState;
+ }
+
+ BluetoothEventLoop getBluetoothEventLoop() {
+ return mEventLoop;
+ }
+
+ private void persistSwitchSetting(boolean setOn) {
+ long origCallerIdentityToken = Binder.clearCallingIdentity();
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.BLUETOOTH_ON,
+ setOn ? 1 : 0);
+ Binder.restoreCallingIdentity(origCallerIdentityToken);
+ }
+
+ private boolean getBluetoothPersistedSetting() {
+ ContentResolver contentResolver = mContext.getContentResolver();
+ return (Settings.Secure.getInt(contentResolver,
+ Settings.Secure.BLUETOOTH_ON, 0) > 0);
+ }
+
+ private void broadcastState(int newState) {
+
+ log("Bluetooth state " + mPublicState + " -> " + newState);
+ if (mPublicState == newState) {
+ return;
+ }
+
+ Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+ intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState);
+ intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mPublicState = newState;
+
+ mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
+ }
+
+ private void dump(PrintWriter pw) {
+ IState currentState = getCurrentState();
+ if (currentState == mPowerOff) {
+ pw.println("Bluetooth OFF - power down\n");
+ } else if (currentState == mWarmUp) {
+ pw.println("Bluetooth OFF - warm up\n");
+ } else if (currentState == mHotOff) {
+ pw.println("Bluetooth OFF - hot but off\n");
+ } else if (currentState == mSwitching) {
+ pw.println("Bluetooth Switching\n");
+ } else if (currentState == mBluetoothOn) {
+ pw.println("Bluetooth ON\n");
+ } else {
+ pw.println("ERROR: Bluetooth UNKNOWN STATE ");
+ }
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index f345a6a..9b9196a 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -52,6 +52,7 @@
private final HashMap<String, Integer> mAuthorizationAgentRequestData;
private final BluetoothService mBluetoothService;
private final BluetoothAdapter mAdapter;
+ private final BluetoothAdapterStateMachine mBluetoothState;
private BluetoothA2dp mA2dp;
private BluetoothInputDevice mInputDevice;
private final Context mContext;
@@ -107,9 +108,11 @@
private static native void classInitNative();
/* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
- BluetoothService bluetoothService) {
+ BluetoothService bluetoothService,
+ BluetoothAdapterStateMachine bluetoothState) {
mBluetoothService = bluetoothService;
mContext = context;
+ mBluetoothState = bluetoothState;
mPasskeyAgentRequestData = new HashMap<String, Integer>();
mAuthorizationAgentRequestData = new HashMap<String, Integer>();
mAdapter = adapter;
@@ -299,8 +302,8 @@
/**
* Called by native code on a PropertyChanged signal from
- * org.bluez.Adapter. This method is also called from Java at
- * {@link BluetoothService.EnableThread#run()} to set the "Pairable"
+ * org.bluez.Adapter. This method is also called from
+ * {@link BluetoothAdapterStateMachine} to set the "Pairable"
* property when Bluetooth is enabled.
*
* @param propValues a string array containing the key and one or more
@@ -334,6 +337,15 @@
return;
adapterProperties.setProperty(name, propValues[1]);
+
+ if (name.equals("Pairable")) {
+ if (pairable.equals("true")) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_PAIRABLE);
+ } else {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECAME_NON_PAIRABLE);
+ }
+ }
+
int mode = BluetoothService.bluezStringToScanMode(
pairable.equals("true"),
discoverable.equals("true"));
@@ -406,6 +418,8 @@
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+ } else if (name.equals("Alias")) {
+ mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
} else if (name.equals("Class")) {
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index d68d8ba..0d95a58 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -39,6 +39,7 @@
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothHealthCallback;
+import android.bluetooth.IBluetoothStateChangeCallback;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -68,13 +69,15 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
-import java.io.InputStreamReader;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -91,7 +94,7 @@
private BluetoothPan mPan;
private boolean mIsAirplaneSensitive;
private boolean mIsAirplaneToggleable;
- private int mBluetoothState;
+ private BluetoothAdapterStateMachine mBluetoothState;
private boolean mRestart = false; // need to call enable() after disable()
private boolean mIsDiscovering;
private int[] mAdapterSdpHandles;
@@ -101,6 +104,8 @@
private final BluetoothBondState mBondState; // local cache of bondings
private final IBatteryStats mBatteryStats;
private final Context mContext;
+ private Map<Integer, IBluetoothStateChangeCallback> mStateChangeTracker =
+ Collections.synchronizedMap(new HashMap<Integer, IBluetoothStateChangeCallback>());
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
@@ -111,9 +116,11 @@
private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
- private static final int MESSAGE_FINISH_DISABLE = 1;
- private static final int MESSAGE_UUID_INTENT = 2;
- private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3;
+ private static final int MESSAGE_UUID_INTENT = 1;
+ private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
+
+ private static final int RFCOMM_RECORD_REAPER = 10;
+ private static final int STATE_CHANGE_REAPER = 11;
// The time (in millisecs) to delay the pairing attempt after the first
// auto pairing attempt fails. We use an exponential delay with
@@ -206,7 +213,6 @@
disableNative();
}
- mBluetoothState = BluetoothAdapter.STATE_OFF;
mIsDiscovering = false;
mBondState = new BluetoothBondState(context, this);
@@ -306,7 +312,9 @@
public synchronized void initAfterRegistration() {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
+ mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
+ mBluetoothState.start();
+ mEventLoop = mBluetoothState.getBluetoothEventLoop();
}
public synchronized void initAfterA2dpRegistration() {
@@ -329,16 +337,16 @@
}
private boolean isEnabledInternal() {
- return mBluetoothState == BluetoothAdapter.STATE_ON;
+ return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
}
public int getBluetoothState() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothState;
+ return getBluetoothStateInternal();
}
int getBluetoothStateInternal() {
- return mBluetoothState;
+ return mBluetoothState.getBluetoothAdapterState();
}
/**
@@ -356,7 +364,9 @@
public synchronized boolean disable(boolean saveSetting) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
- switch (mBluetoothState) {
+ int adapterState = getBluetoothStateInternal();
+
+ switch (adapterState) {
case BluetoothAdapter.STATE_OFF:
return true;
case BluetoothAdapter.STATE_ON:
@@ -364,27 +374,12 @@
default:
return false;
}
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF);
-
- if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
- setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
- BluetoothPanProfileHandler.NAP_BRIDGE);
-
- // Allow 3 seconds for profiles to gracefully disconnect
- // TODO: Introduce a callback mechanism so that each profile can notify
- // BluetoothService when it is done shutting down
- disconnectDevices();
-
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
return true;
}
- private synchronized void disconnectDevices() {
+ synchronized void disconnectDevices() {
// Disconnect devices handled by BluetoothService.
for (BluetoothDevice device: getConnectedInputDevices()) {
disconnectInputDevice(device);
@@ -395,14 +390,11 @@
}
}
- private synchronized void finishDisable(boolean saveSetting) {
- if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) {
- return;
- }
- mEventLoop.stop();
- tearDownNativeDataNative();
- disableNative();
-
+ /**
+ * The Bluetooth has been turned off, but hot. Do bonding, profile,
+ * and internal cleanup
+ */
+ synchronized void finishDisable() {
// mark in progress bondings as cancelled
for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
@@ -430,12 +422,6 @@
mAdapterUuids = null;
mAdapterSdpHandles = null;
- if (saveSetting) {
- persistBluetoothOnSetting(false);
- }
-
- setBluetoothState(BluetoothAdapter.STATE_OFF);
-
// Log bluetooth off to battery stats.
long ident = Binder.clearCallingIdentity();
try {
@@ -451,6 +437,18 @@
}
}
+ /**
+ * power off Bluetooth
+ */
+ synchronized void shutoffBluetooth() {
+ tearDownNativeDataNative();
+ disableNative();
+ if (mRestart) {
+ mRestart = false;
+ enable();
+ }
+ }
+
/** Bring up BT and persist BT on in settings */
public boolean enable() {
return enable(true);
@@ -471,21 +469,29 @@
if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
return false;
}
- if (mBluetoothState != BluetoothAdapter.STATE_OFF) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
+ return true;
+ }
+
+ /**
+ * Turn on Bluetooth Module, Load firmware, and do all the preparation
+ * needed to get the Bluetooth Module ready but keep it not discoverable
+ * and not connectable.
+ */
+ /* package */ synchronized boolean prepareBluetooth() {
+ if (!setupNativeDataNative()) {
return false;
}
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
- setBluetoothState(BluetoothAdapter.STATE_TURNING_ON);
- mEnableThread = new EnableThread(saveSetting);
- mEnableThread.start();
+ mIsDiscovering = false;
+
+ switchConnectable(false);
+ updateSdpRecords();
return true;
}
/** Forcibly restart Bluetooth if it is on */
/* package */ synchronized void restart() {
- if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+ if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
return;
}
mRestart = true;
@@ -494,30 +500,10 @@
}
}
- private synchronized void setBluetoothState(int state) {
- if (state == mBluetoothState) {
- return;
- }
-
- if (DBG) Log.d(TAG, "Bluetooth state " + mBluetoothState + " -> " + state);
-
- Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
- intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState);
- intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
- mBluetoothState = state;
-
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MESSAGE_FINISH_DISABLE:
- finishDisable(msg.arg1 != 0);
- break;
case MESSAGE_UUID_INTENT:
String address = (String)msg.obj;
if (address != null) {
@@ -545,65 +531,6 @@
}
};
- private EnableThread mEnableThread;
-
- private class EnableThread extends Thread {
- private final boolean mSaveSetting;
- public EnableThread(boolean saveSetting) {
- mSaveSetting = saveSetting;
- }
- public void run() {
- boolean res = (enableNative() == 0);
- if (res) {
- int retryCount = 2;
- boolean running = false;
- while ((retryCount-- > 0) && !running) {
- mEventLoop.start();
- // it may take a moment for the other thread to do its
- // thing. Check periodically for a while.
- int pollCount = 5;
- while ((pollCount-- > 0) && !running) {
- if (mEventLoop.isEventLoopRunning()) {
- running = true;
- break;
- }
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {}
- }
- }
- if (!running) {
- Log.e(TAG, "bt EnableThread giving up");
- res = false;
- disableNative();
- }
- }
-
- if (res) {
- if (!setupNativeDataNative()) {
- return;
- }
- if (mSaveSetting) {
- persistBluetoothOnSetting(true);
- }
-
- mIsDiscovering = false;
- mBondState.readAutoPairingData();
- mBondState.initBondState();
- initProfileState();
-
- // This should be the last step of the the enable thread.
- // Because this adds SDP records which asynchronously
- // broadcasts the Bluetooth On State in updateBluetoothState.
- // So we want all internal state setup before this.
- updateSdpRecords();
- } else {
- setBluetoothState(BluetoothAdapter.STATE_OFF);
- }
- mEnableThread = null;
- }
- }
-
private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
//Register SDP records.
int[] svcIdentifiers = new int[uuids.size()];
@@ -650,38 +577,37 @@
* for adapter comes in with UUID property.
* @param uuidsThe uuids of adapter as reported by Bluez.
*/
- synchronized void updateBluetoothState(String uuids) {
- if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) {
- ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
+ /*package*/ synchronized void updateBluetoothState(String uuids) {
+ ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
- if (mAdapterUuids != null &&
- BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
- setBluetoothState(BluetoothAdapter.STATE_ON);
- autoConnect();
- String[] propVal = {"Pairable", getProperty("Pairable")};
- mEventLoop.onPropertyChanged(propVal);
-
- // Log bluetooth on to battery stats.
- long ident = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteBluetoothOn();
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
- disable(false);
- }
- }
+ if (mAdapterUuids != null &&
+ BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
}
}
- private void persistBluetoothOnSetting(boolean bluetoothOn) {
- long origCallerIdentityToken = Binder.clearCallingIdentity();
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
- bluetoothOn ? 1 : 0);
- Binder.restoreCallingIdentity(origCallerIdentityToken);
+ /**
+ * This method is called immediately after Bluetooth module is turned on.
+ * It starts auto-connection and places bluetooth on sign onto the battery
+ * stats
+ */
+ /*package*/ void runBluetooth() {
+ mIsDiscovering = false;
+ mBondState.readAutoPairingData();
+ mBondState.initBondState();
+ initProfileState();
+
+ autoConnect();
+
+ // Log bluetooth on to battery stats.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mBatteryStats.noteBluetoothOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
/*package*/ synchronized boolean attemptAutoPair(String address) {
@@ -818,6 +744,26 @@
public synchronized boolean setScanMode(int mode, int duration) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
"Need WRITE_SECURE_SETTINGS permission");
+ return setScanMode(mode, duration, true);
+ }
+
+ /**
+ * @param on true set the local Bluetooth module to be connectable
+ * but not dicoverable
+ * false set the local Bluetooth module to be not connectable
+ * and not dicoverable
+ */
+ /*package*/ synchronized void switchConnectable(boolean on) {
+ if (on) {
+ // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
+ setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
+ } else {
+ // 0 is a dummy value, does not apply for SCAN_MODE_NONE
+ setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
+ }
+ }
+
+ private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
boolean pairable;
boolean discoverable;
@@ -839,9 +785,15 @@
Log.w(TAG, "Requested invalid scan mode " + mode);
return false;
}
- setPropertyBoolean("Pairable", pairable);
- setPropertyBoolean("Discoverable", discoverable);
+ if (allowOnlyInOnState) {
+ setPropertyBoolean("Pairable", pairable);
+ setPropertyBoolean("Discoverable", discoverable);
+ } else {
+ // allowed to set the property through native layer directly
+ setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0);
+ setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0);
+ }
return true;
}
@@ -899,7 +851,6 @@
return uuids;
}
-
/**
* Returns the user-friendly name of a remote device. This value is
* returned from our local cache, which is updated when onPropertyChange
@@ -920,6 +871,40 @@
}
/**
+ * Returns alias of a remote device. This value is returned from our
+ * local cache, which is updated when onPropertyChange event is received.
+ *
+ * @param address Bluetooth address of remote device.
+ *
+ * @return The alias of the specified remote device.
+ */
+ public synchronized String getRemoteAlias(String address) {
+
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ return null;
+ }
+ return mDeviceProperties.getProperty(address, "Alias");
+ }
+
+ /**
+ * Set the alias of a remote device.
+ *
+ * @param address Bluetooth address of remote device.
+ * @param alias new alias to change to
+ * @return true on success, false on error
+ */
+ public synchronized boolean setRemoteAlias(String address, String alias) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ return false;
+ }
+
+ return setDevicePropertyStringNative(getObjectPathFromAddress(address),
+ "Alias", alias);
+ }
+
+ /**
* Get the discoverability window for the device. A timeout of zero
* means that the device is permanently discoverable (if the device is
* in the discoverable mode).
@@ -1522,7 +1507,7 @@
int pid = Binder.getCallingPid();
mServiceRecordToPid.put(new Integer(handle), new Integer(pid));
try {
- b.linkToDeath(new Reaper(handle, pid), 0);
+ b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0);
} catch (RemoteException e) {}
return handle;
}
@@ -1545,20 +1530,85 @@
}
private class Reaper implements IBinder.DeathRecipient {
- int pid;
- int handle;
- Reaper(int handle, int pid) {
- this.pid = pid;
- this.handle = handle;
+ int mPid;
+ int mHandle;
+ int mType;
+
+ Reaper(int handle, int pid, int type) {
+ mPid = pid;
+ mHandle = handle;
+ mType = type;
}
+
+ Reaper(int pid, int type) {
+ mPid = pid;
+ mType = type;
+ }
+
+ @Override
public void binderDied() {
synchronized (BluetoothService.this) {
- if (DBG) Log.d(TAG, "Tracked app " + pid + " died");
- checkAndRemoveRecord(handle, pid);
+ if (DBG) Log.d(TAG, "Tracked app " + mPid + " died" + "Type:" + mType);
+ if (mType == RFCOMM_RECORD_REAPER) {
+ checkAndRemoveRecord(mHandle, mPid);
+ } else if (mType == STATE_CHANGE_REAPER) {
+ mStateChangeTracker.remove(mPid);
+ }
}
}
}
+
+ @Override
+ public boolean changeApplicationBluetoothState(boolean on,
+ IBluetoothStateChangeCallback callback, IBinder binder) {
+ int pid = Binder.getCallingPid();
+ //mStateChangeTracker is a synchronized map
+ if (!mStateChangeTracker.containsKey(pid)) {
+ if (on) {
+ mStateChangeTracker.put(pid, callback);
+ } else {
+ return false;
+ }
+ } else if (!on) {
+ mStateChangeTracker.remove(pid);
+ }
+
+ if (binder != null) {
+ try {
+ binder.linkToDeath(new Reaper(pid, STATE_CHANGE_REAPER), 0);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ int type;
+ if (on) {
+ type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_ON;
+ } else {
+ type = BluetoothAdapterStateMachine.PER_PROCESS_TURN_OFF;
+ }
+
+ mBluetoothState.sendMessage(type, callback);
+ return true;
+ }
+
+ boolean isApplicationStateChangeTrackerEmpty() {
+ return mStateChangeTracker.isEmpty();
+ }
+
+ void clearApplicationStateChangeTracker() {
+ mStateChangeTracker.clear();
+ }
+
+ Collection<IBluetoothStateChangeCallback> getApplicationStateChangeCallbacks() {
+ return mStateChangeTracker.values();
+ }
+
+ int getNumberOfApplicationStateChangeTrackers() {
+ return mStateChangeTracker.size();
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -1569,14 +1619,10 @@
ContentResolver resolver = context.getContentResolver();
// Query the airplane mode from Settings.System just to make sure that
// some random app is not sending this intent and disabling bluetooth
- boolean enabled = !isAirplaneModeOn();
- // If bluetooth is currently expected to be on, then enable or disable bluetooth
- if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
- if (enabled) {
- enable(false);
- } else {
- disable(false);
- }
+ if (isAirplaneModeOn()) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
+ } else {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
}
} else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -1650,8 +1696,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- dumpBluetoothState(pw);
- if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+ if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
return;
}
@@ -1840,25 +1885,6 @@
}
}
- private void dumpBluetoothState(PrintWriter pw) {
- switch(mBluetoothState) {
- case BluetoothAdapter.STATE_OFF:
- pw.println("Bluetooth OFF\n");
- break;
- case BluetoothAdapter.STATE_TURNING_ON:
- pw.println("Bluetooth TURNING ON\n");
- break;
- case BluetoothAdapter.STATE_TURNING_OFF:
- pw.println("Bluetooth TURNING OFF\n");
- break;
- case BluetoothAdapter.STATE_ON:
- pw.println("Bluetooth ON\n");
- break;
- default:
- pw.println("Bluetooth UNKNOWN STATE " + mBluetoothState);
- }
- }
-
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -2389,7 +2415,7 @@
public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
int prevState) {
// Since this is a binder call check if Bluetooth is on still
- if (mBluetoothState == BluetoothAdapter.STATE_OFF) return;
+ if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
if (!validateProfileConnectionState(state) ||
@@ -2405,6 +2431,10 @@
mAdapterConnectionState = state;
+ if (state == BluetoothProfile.STATE_DISCONNECTED) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
+ }
+
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
@@ -2598,8 +2628,8 @@
/*package*/ native String getAdapterPathNative();
private native int isEnabledNative();
- private native int enableNative();
- private native int disableNative();
+ /*package*/ native int enableNative();
+ /*package*/ native int disableNative();
/*package*/ native Object[] getAdapterPropertiesNative();
private native Object[] getDevicePropertiesNative(String objectPath);
@@ -2629,6 +2659,8 @@
private native boolean setDevicePropertyBooleanNative(String objectPath, String key,
int value);
+ private native boolean setDevicePropertyStringNative(String objectPath, String key,
+ String value);
private native boolean createDeviceNative(String address);
/*package*/ native boolean discoverServicesNative(String objectPath, String pattern);
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 270f512..6f70ab8 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -24,6 +24,7 @@
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.Log;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
@@ -36,6 +37,7 @@
*/
public abstract class SpellCheckerService extends Service {
private static final String TAG = SpellCheckerService.class.getSimpleName();
+ private static final boolean DBG = false;
public static final String SERVICE_INTERFACE =
"android.service.textservice.SpellCheckerService";
@@ -87,6 +89,9 @@
*/
@Override
public final IBinder onBind(final Intent intent) {
+ if (DBG) {
+ Log.w(TAG, "onBind");
+ }
return mBinder;
}
diff --git a/core/java/android/service/textservice/SpellCheckerSession.java b/core/java/android/service/textservice/SpellCheckerSession.java
index 400454d..0dff3a6 100644
--- a/core/java/android/service/textservice/SpellCheckerSession.java
+++ b/core/java/android/service/textservice/SpellCheckerSession.java
@@ -30,7 +30,6 @@
import android.view.textservice.TextInfo;
import java.util.LinkedList;
-import java.util.Locale;
import java.util.Queue;
/**
@@ -125,6 +124,9 @@
*/
public void getSuggestions(
TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+ if (DBG) {
+ Log.w(TAG, "getSuggestions from " + mSpellCheckerInfo.getId());
+ }
// TODO: Handle multiple words suggestions by using WordBreakIterator
mSpellCheckerSessionListenerImpl.getSuggestionsMultiple(
textInfos, suggestionsLimit, sequentialWords);
@@ -186,6 +188,9 @@
public void getSuggestionsMultiple(
TextInfo[] textInfos, int suggestionsLimit, boolean sequentialWords) {
+ if (DBG) {
+ Log.w(TAG, "getSuggestionsMultiple");
+ }
processOrEnqueueTask(
new SpellCheckerParams(TASK_GET_SUGGESTIONS_MULTIPLE, textInfos,
suggestionsLimit, sequentialWords));
@@ -204,6 +209,9 @@
}
private void processOrEnqueueTask(SpellCheckerParams scp) {
+ if (DBG) {
+ Log.d(TAG, "process or enqueue task: " + mISpellCheckerSession);
+ }
if (mISpellCheckerSession == null) {
mPendingTasks.offer(scp);
} else {
@@ -215,6 +223,9 @@
if (!checkOpenConnection()) {
return;
}
+ if (DBG) {
+ Log.w(TAG, "Cancel spell checker tasks.");
+ }
try {
mISpellCheckerSession.cancel();
} catch (RemoteException e) {
@@ -226,6 +237,9 @@
if (!checkOpenConnection()) {
return;
}
+ if (DBG) {
+ Log.w(TAG, "Get suggestions from the spell checker.");
+ }
try {
mISpellCheckerSession.getSuggestionsMultiple(
scp.mTextInfos, scp.mSuggestionsLimit, scp.mSequentialWords);
@@ -254,6 +268,9 @@
private class InternalListener extends ITextServicesSessionListener.Stub {
@Override
public void onServiceConnected(ISpellCheckerSession session) {
+ if (DBG) {
+ Log.w(TAG, "SpellCheckerSession connected.");
+ }
mSpellCheckerSessionListenerImpl.onServiceConnected(session);
}
}
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 1926c92..b4e8ab4 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -227,7 +227,7 @@
private boolean mFirstIdle = true;
public SynthThread() {
- super(SYNTH_THREAD_NAME, android.os.Process.THREAD_PRIORITY_AUDIO);
+ super(SYNTH_THREAD_NAME, android.os.Process.THREAD_PRIORITY_DEFAULT);
}
@Override
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index c6ffe58..5926db3 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -281,10 +281,29 @@
}
/**
- * return a negative number if a is less than b, a positive number if a is
- * greater than b, and 0 if they are equal.
+ * Compare two {@code Time} objects and return a negative number if {@code
+ * a} is less than {@code b}, a positive number if {@code a} is greater than
+ * {@code b}, or 0 if they are equal.
+ *
+ * @param a first {@code Time} instance to compare
+ * @param b second {@code Time} instance to compare
+ * @throws NullPointerException if either argument is {@code null}
+ * @throws IllegalArgumentException if {@link #allDay} is true but {@code
+ * hour}, {@code minute}, and {@code second} are not 0.
+ * @return a negative result if {@code a} is earlier, a positive result if
+ * {@code a} is earlier, or 0 if they are equal.
*/
- native public static int compare(Time a, Time b);
+ public static int compare(Time a, Time b) {
+ if (a == null) {
+ throw new NullPointerException("a == null");
+ } else if (b == null) {
+ throw new NullPointerException("b == null");
+ }
+
+ return nativeCompare(a, b);
+ }
+
+ private static native int nativeCompare(Time a, Time b);
/**
* Print the current value given the format string provided. See man
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5ab2024..d9efe0c 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -25,16 +25,18 @@
import android.util.DisplayMetrics;
import android.util.Slog;
+/**
+ * Provides information about the display size and density.
+ */
public class Display {
static final String TAG = "Display";
static final boolean DEBUG_COMPAT = false;
/**
- * Specify the default Display
+ * The default Display id.
*/
public static final int DEFAULT_DISPLAY = 0;
-
/**
* Use {@link android.view.WindowManager#getDefaultDisplay()
* WindowManager.getDefaultDisplay()} to create a Display object.
@@ -55,16 +57,6 @@
init(display);
}
- /** @hide */
- public static void setCompatibilityInfo(CompatibilityInfo compatInfo) {
- if (compatInfo != null && (compatInfo.isScalingRequired()
- || !compatInfo.supportsScreen())) {
- sCompatibilityInfo = compatInfo;
- } else {
- sCompatibilityInfo = null;
- }
- }
-
/**
* Returns the index of this display. This is currently undefined; do
* not use.
@@ -80,25 +72,29 @@
native static int getDisplayCount();
/**
- * Returns the raw size of the display, in pixels. Note that this
- * should <em>not</em> generally be used for computing layouts, since
- * a device will typically have screen decoration (such as a status bar)
+ * Gets the size of the display, in pixels.
+ * <p>
+ * Note that this value should <em>not</em> be used for computing layouts,
+ * since a device will typically have screen decoration (such as a status bar)
* along the edges of the display that reduce the amount of application
- * space available from the raw size returned here. This value is
- * adjusted for you based on the current rotation of the display.
+ * space available from the size returned here. Layouts should instead use
+ * the window size.
+ * </p><p>
+ * The size is adjusted based on the current rotation of the display.
+ * </p><p>
+ * The size returned by this method does not necessarily represent the
+ * actual raw size (native resolution) of the display. The returned size may
+ * be adjusted to exclude certain system decor elements that are always visible.
+ * It may also be scaled to provide compatibility with older applications that
+ * were originally designed for smaller displays.
+ * </p>
+ *
+ * @param outSize A {@link Point} object to receive the size information.
*/
public void getSize(Point outSize) {
getSizeInternal(outSize, true);
}
- /**
- * Returns the raw size of the display, in pixels. Note that this
- * should <em>not</em> generally be used for computing layouts, since
- * a device will typically have screen decoration (such as a status bar)
- * along the edges of the display that reduce the amount of application
- * space available from the raw size returned here. This value is
- * adjusted for you based on the current rotation of the display.
- */
private void getSizeInternal(Point outSize, boolean doCompat) {
try {
IWindowManager wm = getWindowManager();
@@ -118,8 +114,8 @@
} else {
// This is just for boot-strapping, initializing the
// system process before the window manager is up.
- outSize.x = getRealWidth();
- outSize.y = getRealHeight();
+ outSize.x = getRawWidth();
+ outSize.y = getRawHeight();
}
if (DEBUG_COMPAT && doCompat) Slog.v(TAG, "Returning display size: " + outSize);
} catch (RemoteException e) {
@@ -128,7 +124,10 @@
}
/**
- * This is just easier for some parts of the framework.
+ * Gets the size of the display as a rectangle, in pixels.
+ *
+ * @param outSize A {@link Rect} object to receive the size information.
+ * @see #getSize(Point)
*/
public void getRectSize(Rect outSize) {
synchronized (mTmpPoint) {
@@ -182,14 +181,49 @@
}
}
- /** @hide Returns the actual screen size, not including any decor. */
- native public int getRealWidth();
- /** @hide Returns the actual screen size, not including any decor. */
- native public int getRealHeight();
+ /**
+ * Gets the real size of the display without subtracting any window decor or
+ * applying any compatibility scale factors.
+ * <p>
+ * The real size may be smaller than the raw size when the window manager
+ * is emulating a smaller display (using adb shell am display-size).
+ * </p><p>
+ * The size is adjusted based on the current rotation of the display.
+ * </p>
+ * @hide
+ */
+ public void getRealSize(Point outSize) {
+ try {
+ IWindowManager wm = getWindowManager();
+ if (wm != null) {
+ wm.getRealDisplaySize(outSize);
+ } else {
+ // This is just for boot-strapping, initializing the
+ // system process before the window manager is up.
+ outSize.x = getRawWidth();
+ outSize.y = getRawHeight();
+ }
+ } catch (RemoteException e) {
+ Slog.w("Display", "Unable to get real display size", e);
+ }
+ }
- /** @hide special for when we are faking the screen size. */
+ /**
+ * Gets the raw width of the display, in pixels.
+ * <p>
+ * The size is adjusted based on the current rotation of the display.
+ * </p>
+ * @hide
+ */
native public int getRawWidth();
- /** @hide special for when we are faking the screen size. */
+
+ /**
+ * Gets the raw height of the display, in pixels.
+ * <p>
+ * The size is adjusted based on the current rotation of the display.
+ * </p>
+ * @hide
+ */
native public int getRawHeight();
/**
@@ -235,17 +269,24 @@
}
/**
- * Initialize a DisplayMetrics object from this display's data.
- *
- * @param outMetrics
+ * Gets display metrics that describe the size and density of this display.
+ * <p>
+ * The size is adjusted based on the current rotation of the display.
+ * </p><p>
+ * The size returned by this method does not necessarily represent the
+ * actual raw size (native resolution) of the display. The returned size may
+ * be adjusted to exclude certain system decor elements that are always visible.
+ * It may also be scaled to provide compatibility with older applications that
+ * were originally designed for smaller displays.
+ * </p>
+ *
+ * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
*/
public void getMetrics(DisplayMetrics outMetrics) {
synchronized (mTmpPoint) {
getSizeInternal(mTmpPoint, false);
- outMetrics.widthPixels = mTmpPoint.x;
- outMetrics.heightPixels = mTmpPoint.y;
+ getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
}
- getNonSizeMetrics(outMetrics);
CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
if (ci != null) {
@@ -257,22 +298,44 @@
}
/**
- * Initialize a DisplayMetrics object from this display's data.
- *
- * @param outMetrics
+ * Gets display metrics based on the real size of this display.
* @hide
*/
public void getRealMetrics(DisplayMetrics outMetrics) {
- outMetrics.widthPixels = getRealWidth();
- outMetrics.heightPixels = getRealHeight();
- getNonSizeMetrics(outMetrics);
+ synchronized (mTmpPoint) {
+ getRealSize(mTmpPoint);
+ getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+ }
}
- private void getNonSizeMetrics(DisplayMetrics outMetrics) {
+ /**
+ * If the display is mirrored to an external HDMI display, returns the
+ * width of that display.
+ * @hide
+ */
+ public int getRawExternalWidth() {
+ return 1280;
+ }
+
+ /**
+ * If the display is mirrored to an external HDMI display, returns the
+ * height of that display.
+ * @hide
+ */
+ public int getRawExternalHeight() {
+ return 720;
+ }
+
+ /**
+ * Gets display metrics based on an explicit assumed display size.
+ * @hide
+ */
+ public void getMetricsWithSize(DisplayMetrics outMetrics,
+ int width, int height) {
outMetrics.densityDpi = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
- outMetrics.noncompatWidthPixels = outMetrics.widthPixels;
- outMetrics.noncompatHeightPixels = outMetrics.heightPixels;
+ outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
+ outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
outMetrics.density = outMetrics.noncompatDensity = mDensity;
outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
@@ -315,8 +378,6 @@
private static boolean sInitialized = false;
private static IWindowManager sWindowManager;
- private static volatile CompatibilityInfo sCompatibilityInfo;
-
/**
* Returns a display object which uses the metric's width/height instead.
* @hide
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index f4c0249..8f4ece0 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -54,4 +54,11 @@
* @return boolean true if the display list is able to be replayed, false otherwise.
*/
abstract boolean isValid();
+
+ /**
+ * Return the amount of memory used by this display list.
+ *
+ * @return The size of this display list in bytes
+ */
+ abstract int getSize();
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d22fa6e..a7fe95d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -51,7 +51,7 @@
// The native renderer will be destroyed when this object dies.
// DO NOT overwrite this reference once it is set.
- @SuppressWarnings("unused")
+ @SuppressWarnings({"unused", "FieldCanBeLocal"})
private CanvasFinalizer mFinalizer;
private int mWidth;
@@ -277,14 +277,25 @@
///////////////////////////////////////////////////////////////////////////
/**
+ * Must match Caches::FlushMode values
+ *
* @see #flushCaches(int)
*/
- public static final int FLUSH_CACHES_MODERATE = 0;
+ public static final int FLUSH_CACHES_LAYERS = 0;
+
+ /**
+ * Must match Caches::FlushMode values
+ *
+ * @see #flushCaches(int)
+ */
+ public static final int FLUSH_CACHES_MODERATE = 1;
/**
+ * Must match Caches::FlushMode values
+ *
* @see #flushCaches(int)
*/
- public static final int FLUSH_CACHES_FULL = 1;
+ public static final int FLUSH_CACHES_FULL = 2;
/**
* Flush caches to reclaim as much memory as possible. The amount of memory
@@ -319,6 +330,12 @@
private static native void nDestroyDisplayList(int displayList);
+ static int getDisplayListSize(int displayList) {
+ return nGetDisplayListSize(displayList);
+ }
+
+ private static native int nGetDisplayListSize(int displayList);
+
@Override
public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) {
return nDrawDisplayList(mRenderer,
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 9e649cea..4ca5e98 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -82,6 +82,12 @@
}
}
+ @Override
+ int getSize() {
+ if (mFinalizer == null) return 0;
+ return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList);
+ }
+
private static class DisplayListFinalizer {
final int mNativeDisplayList;
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index a491a0b..fd3b9e5 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -54,7 +54,10 @@
@Override
void destroy() {
- if (mFinalizer != null) mFinalizer.destroy();
+ if (mFinalizer != null) {
+ mFinalizer.destroy();
+ mFinalizer = null;
+ }
mLayer = 0;
}
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 078222b..c987f48 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -38,7 +38,7 @@
class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
- private static final int POOL_LIMIT = 50;
+ private static final int POOL_LIMIT = 25;
private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(
Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index 7adac1c..41f16e2 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -24,7 +24,6 @@
* {@link Canvas} that can be used to render into an FBO using OpenGL.
*/
class GLES20RenderLayer extends GLES20Layer {
-
private int mLayerWidth;
private int mLayerHeight;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 503b54b..4e4923b 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -33,6 +33,8 @@
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
+import static javax.microedition.khronos.egl.EGL10.*;
+
/**
* Interface for rendering a ViewAncestor using hardware acceleration.
*
@@ -70,6 +72,15 @@
static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
/**
+ * System property used to debug EGL configuration choice.
+ *
+ * Possible values:
+ * "choice", print the chosen configuration only
+ * "all", print all possible configurations
+ */
+ static final String PRINT_CONFIG_PROPERTY = "hwui.print_config";
+
+ /**
* Turn on to draw dirty regions every other frame.
*/
private static final boolean DEBUG_DIRTY_REGION = false;
@@ -129,6 +140,13 @@
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
+ * Destoys the layers used by the specified view hierarchy.
+ *
+ * @param view The root of the view hierarchy
+ */
+ abstract void destroyLayers(View view);
+
+ /**
* This method should be invoked whenever the current hardware renderer
* context should be reset.
*/
@@ -272,7 +290,7 @@
* see {@link android.content.ComponentCallbacks}
*/
static void trimMemory(int level) {
- Gl20Renderer.flushCaches(level);
+ Gl20Renderer.trimMemory(level);
}
/**
@@ -389,33 +407,33 @@
*/
static String getEGLErrorString(int error) {
switch (error) {
- case EGL10.EGL_SUCCESS:
+ case EGL_SUCCESS:
return "EGL_SUCCESS";
- case EGL10.EGL_NOT_INITIALIZED:
+ case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
- case EGL10.EGL_BAD_ACCESS:
+ case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
- case EGL10.EGL_BAD_ALLOC:
+ case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
- case EGL10.EGL_BAD_ATTRIBUTE:
+ case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
- case EGL10.EGL_BAD_CONFIG:
+ case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
- case EGL10.EGL_BAD_CONTEXT:
+ case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
- case EGL10.EGL_BAD_CURRENT_SURFACE:
+ case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
- case EGL10.EGL_BAD_DISPLAY:
+ case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
- case EGL10.EGL_BAD_MATCH:
+ case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
- case EGL10.EGL_BAD_NATIVE_PIXMAP:
+ case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
- case EGL10.EGL_BAD_NATIVE_WINDOW:
+ case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
- case EGL10.EGL_BAD_PARAMETER:
+ case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
- case EGL10.EGL_BAD_SURFACE:
+ case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
case EGL11.EGL_CONTEXT_LOST:
return "EGL_CONTEXT_LOST";
@@ -432,7 +450,7 @@
void checkEglErrors() {
if (isEnabled()) {
int error = sEgl.eglGetError();
- if (error != EGL10.EGL_SUCCESS) {
+ if (error != EGL_SUCCESS) {
// something bad has happened revert to
// normal rendering.
fallback(error != EGL11.EGL_CONTEXT_LOST);
@@ -460,7 +478,7 @@
if (mGl != null) {
int err = sEgl.eglGetError();
- if (err != EGL10.EGL_SUCCESS) {
+ if (err != EGL_SUCCESS) {
destroy(true);
setRequested(false);
} else {
@@ -489,15 +507,17 @@
abstract GLES20Canvas createCanvas();
+ abstract int[] getConfig(boolean dirtyRegions);
+
void initializeEgl() {
synchronized (sEglLock) {
if (sEgl == null && sEglConfig == null) {
sEgl = (EGL10) EGLContext.getEGL();
// Get to the default display.
- sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (sEglDisplay == EGL10.EGL_NO_DISPLAY) {
+ if (sEglDisplay == EGL_NO_DISPLAY) {
throw new RuntimeException("eglGetDisplay failed "
+ getEGLErrorString(sEgl.eglGetError()));
}
@@ -535,19 +555,63 @@
}
private EGLConfig chooseEglConfig() {
- int[] configsCount = new int[1];
EGLConfig[] configs = new EGLConfig[1];
+ int[] configsCount = new int[1];
int[] configSpec = getConfig(sDirtyRegions);
+
+ // Debug
+ final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
+ if ("all".equalsIgnoreCase(debug)) {
+ sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
+
+ EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
+ sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
+ configsCount[0], configsCount);
+
+ for (EGLConfig config : debugConfigs) {
+ printConfig(config);
+ }
+ }
+
if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
throw new IllegalArgumentException("eglChooseConfig failed " +
getEGLErrorString(sEgl.eglGetError()));
} else if (configsCount[0] > 0) {
+ if ("choice".equalsIgnoreCase(debug)) {
+ printConfig(configs[0]);
+ }
return configs[0];
}
+
return null;
}
- abstract int[] getConfig(boolean dirtyRegions);
+ private void printConfig(EGLConfig config) {
+ int[] value = new int[1];
+
+ Log.d(LOG_TAG, "EGL configuration " + config + ":");
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
+ Log.d(LOG_TAG, " RED_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
+ Log.d(LOG_TAG, " GREEN_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
+ Log.d(LOG_TAG, " BLUE_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
+ Log.d(LOG_TAG, " ALPHA_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
+ Log.d(LOG_TAG, " DEPTH_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
+ Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]);
+
+ sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
+ Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
+ }
GL createEglSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException {
// Check preconditions.
@@ -565,26 +629,15 @@
+ "from multiple threads");
}
- /*
- * The window size has changed, so we need to create a new
- * surface.
- */
- if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
- /*
- * Unbind and destroy the old EGL surface, if
- * there is one.
- */
- sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
- }
+ // In case we need to destroy an existing surface
+ destroySurface();
// Create an EGL surface we can render into.
mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, holder, null);
- if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+ if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
int error = sEgl.eglGetError();
- if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+ if (error == EGL_BAD_NATIVE_WINDOW) {
Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
return null;
}
@@ -621,22 +674,13 @@
}
EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
- int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL10.EGL_NONE };
+ int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
- return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT,
- mGlVersion != 0 ? attrib_list : null);
+ return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
+ mGlVersion != 0 ? attribs : null);
}
@Override
- void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
- SurfaceHolder holder) throws Surface.OutOfResourcesException {
- if (isRequested()) {
- checkEglErrors();
- super.initializeIfNeeded(width, height, attachInfo, holder);
- }
- }
-
- @Override
void destroy(boolean full) {
if (full && mCanvas != null) {
mCanvas = null;
@@ -646,22 +690,27 @@
mDestroyed = true;
- sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+ destroySurface();
- mEglSurface = null;
mGl = null;
setEnabled(false);
}
+ void destroySurface() {
+ if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
+ sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
+ mEglSurface = null;
+ }
+ }
+
@Override
void invalidate() {
// Cancels any existing buffer to ensure we'll get a buffer
// of the right size before we call eglSwapBuffers
- sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
@Override
@@ -671,6 +720,7 @@
@Override
void setup(int width, int height) {
+ checkCurrent();
mCanvas.setViewport(width, height);
}
@@ -764,7 +814,7 @@
* {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
* {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
*/
- private int checkCurrent() {
+ int checkCurrent() {
if (mEglThread != Thread.currentThread()) {
throw new IllegalStateException("Hardware acceleration can only be used with a " +
"single UI thread.\nOriginal thread: " + mEglThread + "\n" +
@@ -772,7 +822,7 @@
}
if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
- !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
+ !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
@@ -792,6 +842,9 @@
static class Gl20Renderer extends GlRenderer {
private GLES20Canvas mGlCanvas;
+ private static EGLSurface sPbuffer;
+ private static final Object[] sPbufferLock = new Object[0];
+
Gl20Renderer(boolean translucent) {
super(2, translucent);
}
@@ -804,16 +857,16 @@
@Override
int[] getConfig(boolean dirtyRegions) {
return new int[] {
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
- EGL10.EGL_ALPHA_SIZE, 8,
- EGL10.EGL_DEPTH_SIZE, 0,
- EGL10.EGL_STENCIL_SIZE, 0,
- EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
(dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
- EGL10.EGL_NONE
+ EGL_NONE
};
}
@@ -871,14 +924,56 @@
return ((GLES20TextureLayer) layer).getSurfaceTexture();
}
+ @Override
+ void destroyLayers(View view) {
+ if (view != null && isEnabled()) {
+ checkCurrent();
+ destroyHardwareLayer(view);
+ GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
+ }
+ }
+
+ private void destroyHardwareLayer(View view) {
+ if (view.destroyLayer()) {
+ view.invalidate(true);
+ }
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+
+ int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ destroyHardwareLayer(group.getChildAt(i));
+ }
+ }
+ }
+
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
return new Gl20Renderer(translucent);
}
return null;
}
-
- static void flushCaches(int level) {
+
+ static void trimMemory(int level) {
+ if (sEgl == null || sEglConfig == null) return;
+
+ EGLContext eglContext = sEglContextStorage.get();
+ // We do not have OpenGL objects
+ if (eglContext == null) {
+ return;
+ } else {
+ synchronized (sPbufferLock) {
+ // Create a temporary 1x1 pbuffer so we have a context
+ // to clear our OpenGL objects
+ if (sPbuffer == null) {
+ sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
+ EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
+ });
+ }
+ }
+ sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
+ }
+
switch (level) {
case ComponentCallbacks.TRIM_MEMORY_MODERATE:
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index ad17edf..81cd798 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -55,6 +55,7 @@
boolean inputMethodClientHasFocus(IInputMethodClient client);
void getDisplaySize(out Point size);
+ void getRealDisplaySize(out Point size);
int getMaximumSizeDimension();
void setForcedDisplaySize(int longDimen, int shortDimen);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 88f59d4..da5c7b2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1123,7 +1123,10 @@
}
/**
- * Button constant: Primary button (left mouse button, stylus tip).
+ * Button constant: Primary button (left mouse button).
+ *
+ * This button constant is not set in response to simple touches with a finger
+ * or stylus tip. The user must actually push a button.
*
* @see #getButtonState
*/
@@ -1215,55 +1218,32 @@
public static final int TOOL_TYPE_UNKNOWN = 0;
/**
- * Tool type constant: The tool is a finger directly touching the display.
- *
- * This is a <em>direct</em> positioning tool.
+ * Tool type constant: The tool is a finger.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_FINGER = 1;
/**
- * Tool type constant: The tool is a stylus directly touching the display
- * or hovering slightly above it.
- *
- * This is a <em>direct</em> positioning tool.
+ * Tool type constant: The tool is a stylus.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_STYLUS = 2;
/**
- * Tool type constant: The tool is a mouse or trackpad that translates
- * relative motions into cursor movements on the display.
- *
- * This is an <em>indirect</em> positioning tool.
+ * Tool type constant: The tool is a mouse or trackpad.
*
* @see #getToolType
*/
public static final int TOOL_TYPE_MOUSE = 3;
/**
- * Tool type constant: The tool is a finger on a touch pad that is not
- * directly attached to the display. Finger movements on the touch pad
- * may be translated into touches on the display, possibly with visual feedback.
- *
- * This is an <em>indirect</em> positioning tool.
+ * Tool type constant: The tool is an eraser or a stylus being used in an inverted posture.
*
* @see #getToolType
*/
- public static final int TOOL_TYPE_INDIRECT_FINGER = 4;
-
- /**
- * Tool type constant: The tool is a stylus on a digitizer tablet that is not
- * attached to the display. Stylus movements on the digitizer may be translated
- * into touches on the display, possibly with visual feedback.
- *
- * This is an <em>indirect</em> positioning tool.
- *
- * @see #getToolType
- */
- public static final int TOOL_TYPE_INDIRECT_STYLUS = 5;
+ public static final int TOOL_TYPE_ERASER = 4;
// NOTE: If you add a new tool type here you must also add it to:
// native/include/android/input.h
@@ -1276,8 +1256,7 @@
names.append(TOOL_TYPE_FINGER, "TOOL_TYPE_FINGER");
names.append(TOOL_TYPE_STYLUS, "TOOL_TYPE_STYLUS");
names.append(TOOL_TYPE_MOUSE, "TOOL_TYPE_MOUSE");
- names.append(TOOL_TYPE_INDIRECT_FINGER, "TOOL_TYPE_INDIRECT_FINGER");
- names.append(TOOL_TYPE_INDIRECT_STYLUS, "TOOL_TYPE_INDIRECT_STYLUS");
+ names.append(TOOL_TYPE_ERASER, "TOOL_TYPE_ERASER");
}
// Private value for history pos that obtains the current sample.
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index c913bb3..836867b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -161,6 +161,9 @@
*/
public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001;
+ // The mSurfaceControl will only be present for Surfaces used by the window
+ // server or system processes. When this class is parceled we defer to the
+ // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface.
@SuppressWarnings("unused")
private int mSurfaceControl;
@SuppressWarnings("unused")
@@ -202,6 +205,19 @@
native private static void nativeClassInit();
static { nativeClassInit(); }
+ /**
+ * Create Surface from a SurfaceTexture.
+ *
+ * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
+ * @hide
+ */
+ public Surface(SurfaceTexture surfaceTexture) {
+ if (DEBUG_RELEASE) {
+ mCreationStack = new Exception();
+ }
+ mCanvas = new CompatibleCanvas();
+ initFromSurfaceTexture(surfaceTexture);
+ }
/**
* create a surface
@@ -505,5 +521,7 @@
private native void init(Parcel source);
+ private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
+
private native int getIdentity();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c68b01c..580d450 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -672,19 +672,23 @@
private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
/**
- * This view is visible. Use with {@link #setVisibility(int)}.
+ * This view is visible.
+ * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+ * android:visibility}.
*/
public static final int VISIBLE = 0x00000000;
/**
* This view is invisible, but it still takes up space for layout purposes.
- * Use with {@link #setVisibility(int)}.
+ * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+ * android:visibility}.
*/
public static final int INVISIBLE = 0x00000004;
/**
* This view is invisible, and it doesn't take any space for layout
- * purposes. Use with {@link #setVisibility(int)}.
+ * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
+ * android:visibility}.
*/
public static final int GONE = 0x00000008;
@@ -2294,8 +2298,8 @@
private Bitmap mDrawingCache;
private Bitmap mUnscaledDrawingCache;
- private DisplayList mDisplayList;
private HardwareLayer mHardwareLayer;
+ DisplayList mDisplayList;
/**
* When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -3903,6 +3907,7 @@
int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
getLocationOnScreen(locationOnScreen);
+ bounds.offsetTo(0, 0);
bounds.offset(locationOnScreen[0], locationOnScreen[1]);
info.setBoundsInScreen(bounds);
@@ -4280,6 +4285,36 @@
}
/**
+ * Set whether or not this view should account for system screen decorations
+ * such as the status bar and inset its content. This allows this view to be
+ * positioned in absolute screen coordinates and remain visible to the user.
+ *
+ * <p>This should only be used by top-level window decor views.
+ *
+ * @param fitSystemWindows true to inset content for system screen decorations, false for
+ * default behavior.
+ *
+ * @attr ref android.R.styleable#View_fitsSystemWindows
+ */
+ public void setFitsSystemWindows(boolean fitSystemWindows) {
+ setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
+ }
+
+ /**
+ * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
+ * will account for system screen decorations such as the status bar and inset its
+ * content. This allows the view to be positioned in absolute screen coordinates
+ * and remain visible to the user.
+ *
+ * @return true if this view will adjust its content bounds for system screen decorations.
+ *
+ * @attr ref android.R.styleable#View_fitsSystemWindows
+ */
+ public boolean fitsSystemWindows() {
+ return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
+ }
+
+ /**
* Returns the visibility status for this view.
*
* @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -9195,10 +9230,7 @@
destroyDrawingCache();
- if (mHardwareLayer != null) {
- mHardwareLayer.destroy();
- mHardwareLayer = null;
- }
+ destroyLayer();
if (mDisplayList != null) {
mDisplayList.invalidate();
@@ -9570,21 +9602,10 @@
// Destroy any previous software drawing cache if needed
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
- if (mHardwareLayer != null) {
- mHardwareLayer.destroy();
- mHardwareLayer = null;
- }
+ destroyLayer();
// fall through - unaccelerated views may use software layer mechanism instead
case LAYER_TYPE_SOFTWARE:
- if (mDrawingCache != null) {
- mDrawingCache.recycle();
- mDrawingCache = null;
- }
-
- if (mUnscaledDrawingCache != null) {
- mUnscaledDrawingCache.recycle();
- mUnscaledDrawingCache = null;
- }
+ destroyDrawingCache();
break;
default:
break;
@@ -9655,7 +9676,8 @@
* @return A HardwareLayer ready to render, or null if an error occurred.
*/
HardwareLayer getHardwareLayer() {
- if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+ if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
+ !mAttachInfo.mHardwareRenderer.isEnabled()) {
return null;
}
@@ -9710,6 +9732,15 @@
return mHardwareLayer;
}
+ boolean destroyLayer() {
+ if (mHardwareLayer != null) {
+ mHardwareLayer.destroy();
+ mHardwareLayer = null;
+ return true;
+ }
+ return false;
+ }
+
/**
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 4acf48c..96e550e 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -420,7 +420,7 @@
*
* @hide
*/
- public static long getViewAncestorInstanceCount() {
+ public static long getViewRootImplCount() {
return Debug.countInstancesOfClass(ViewRootImpl.class);
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 6f90971..7a1acfd 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -36,7 +36,6 @@
import android.util.SparseArray;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
@@ -788,7 +787,7 @@
final View[] children = mChildren;
for (int i = 0; i < childrenCount; i++) {
View child = children[i];
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
+ if ((child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
child.findViewsWithText(outViews, text);
}
}
@@ -2162,6 +2161,11 @@
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
+ // If the view is not the topmost one in the view hierarchy and it is
+ // marked as the logical root of a view hierarchy, do not go any deeper.
+ if ((!(getParent() instanceof ViewRootImpl)) && (mPrivateFlags & IS_ROOT_NAMESPACE) != 0) {
+ return;
+ }
for (int i = 0, count = mChildrenCount; i < count; i++) {
View child = mChildren[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
@@ -2854,7 +2858,7 @@
// display lists to render, force an invalidate to allow the animation to
// continue drawing another frame
invalidate(true);
- if (a.hasAlpha()) {
+ if (a.hasAlpha() && (child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
// alpha animations should cause the child to recreate its display list
child.invalidate(true);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 470493d..0bd5a2a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -80,6 +80,7 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -540,6 +541,29 @@
}
}
+ private void destroyHardwareResources() {
+ if (mAttachInfo.mHardwareRenderer != null) {
+ if (mAttachInfo.mHardwareRenderer.isEnabled()) {
+ mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+ }
+ mAttachInfo.mHardwareRenderer.destroy(false);
+ }
+ }
+
+ void destroyHardwareLayers() {
+ if (mThread != Thread.currentThread()) {
+ if (mAttachInfo.mHardwareRenderer != null &&
+ mAttachInfo.mHardwareRenderer.isEnabled()) {
+ HardwareRenderer.trimMemory(ComponentCallbacks.TRIM_MEMORY_MODERATE);
+ }
+ } else {
+ if (mAttachInfo.mHardwareRenderer != null &&
+ mAttachInfo.mHardwareRenderer.isEnabled()) {
+ mAttachInfo.mHardwareRenderer.destroyLayers(mView);
+ }
+ }
+ }
+
private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
@@ -824,8 +848,10 @@
if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
// NOTE -- system code, won't try to do compat mode.
Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
- desiredWindowWidth = disp.getRealWidth();
- desiredWindowHeight = disp.getRealHeight();
+ Point size = new Point();
+ disp.getRealSize(size);
+ desiredWindowWidth = size.x;
+ desiredWindowHeight = size.y;
} else {
DisplayMetrics packageMetrics =
mView.getContext().getResources().getDisplayMetrics();
@@ -868,9 +894,7 @@
attachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
- if (mAttachInfo.mHardwareRenderer != null) {
- mAttachInfo.mHardwareRenderer.destroy(false);
- }
+ destroyHardwareResources();
}
if (viewVisibility == View.GONE) {
// After making a window gone, we will count it as being
@@ -979,8 +1003,10 @@
if (lp.type == WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL) {
// NOTE -- system code, won't try to do compat mode.
Display disp = WindowManagerImpl.getDefault().getDefaultDisplay();
- desiredWindowWidth = disp.getRealWidth();
- desiredWindowHeight = disp.getRealHeight();
+ Point size = new Point();
+ disp.getRealSize(size);
+ desiredWindowWidth = size.x;
+ desiredWindowHeight = size.y;
} else {
DisplayMetrics packageMetrics = res.getDisplayMetrics();
desiredWindowWidth = packageMetrics.widthPixels;
@@ -1511,7 +1537,8 @@
}
}
- boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw();
+ boolean cancelDraw = attachInfo.mTreeObserver.dispatchOnPreDraw() ||
+ viewVisibility != View.VISIBLE;
if (!cancelDraw && !newSurface) {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
@@ -1565,8 +1592,11 @@
if (fullRedrawNeeded) {
mFullRedrawNeeded = true;
}
- // Try again
- scheduleTraversals();
+
+ if (viewVisibility == View.VISIBLE) {
+ // Try again
+ scheduleTraversals();
+ }
}
}
@@ -3484,6 +3514,31 @@
public void debug() {
mView.debug();
}
+
+ public void dumpGfxInfo(PrintWriter pw, int[] info) {
+ if (mView != null) {
+ getGfxInfo(mView, info);
+ } else {
+ info[0] = info[1] = 0;
+ }
+ }
+
+ private void getGfxInfo(View view, int[] info) {
+ DisplayList displayList = view.mDisplayList;
+ info[0]++;
+ if (displayList != null) {
+ info[1] += displayList.getSize();
+ }
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+
+ int count = group.getChildCount();
+ for (int i = 0; i < count; i++) {
+ getGfxInfo(group.getChildAt(i), info);
+ }
+ }
+ }
public void die(boolean immediate) {
if (immediate) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index a451bb5..5ef4f3e 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -24,6 +24,9 @@
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
import java.util.HashMap;
final class WindowLeaked extends AndroidRuntimeException {
@@ -392,7 +395,7 @@
leak.setStackTrace(root.getLocation().getStackTrace());
Log.e("WindowManager", leak.getMessage(), leak);
}
-
+
removeViewLocked(i);
i--;
count--;
@@ -410,6 +413,59 @@
}
}
+ /**
+ * @hide
+ */
+ public void trimLocalMemory() {
+ synchronized (this) {
+ if (mViews == null) return;
+ int count = mViews.length;
+ for (int i = 0; i < count; i++) {
+ mRoots[i].destroyHardwareLayers();
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void dumpGfxInfo(FileDescriptor fd) {
+ FileOutputStream fout = new FileOutputStream(fd);
+ PrintWriter pw = new PrintWriter(fout);
+ try {
+ synchronized (this) {
+ if (mViews != null) {
+ pw.println("View hierarchy:");
+
+ final int count = mViews.length;
+
+ int viewsCount = 0;
+ int displayListsSize = 0;
+ int[] info = new int[2];
+
+ for (int i = 0; i < count; i++) {
+ ViewRootImpl root = mRoots[i];
+ root.dumpGfxInfo(pw, info);
+
+ String name = root.getClass().getName() + '@' +
+ Integer.toHexString(hashCode());
+ pw.printf(" %s: %d views, %.2f kB (display lists)\n",
+ name, info[0], info[1] / 1024.0f);
+
+ viewsCount += info[0];
+ displayListsSize += info[1];
+ }
+
+ pw.printf("\nTotal ViewRootImpl: %d\n", count);
+ pw.printf("Total Views: %d\n", viewsCount);
+ pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f);
+ }
+ }
+ } finally {
+ pw.flush();
+ }
+ }
+
public void setStoppedState(IBinder token, boolean stopped) {
synchronized (this) {
if (mViews == null)
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 83c73cb..a80c2a7 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -67,13 +67,17 @@
private static final String LOG_TAG = "AccessibilityManager";
+ /** @hide */
+ public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
+
+ /** @hide */
+ public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
+
static final Object sInstanceSync = new Object();
private static AccessibilityManager sInstance;
- private static final int DO_SET_ACCESSIBILITY_ENABLED = 10;
-
- private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20;
+ private static final int DO_SET_STATE = 10;
final IAccessibilityManager mService;
@@ -100,13 +104,8 @@
}
final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
- public void setEnabled(boolean enabled) {
- mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
- }
-
- public void setTouchExplorationEnabled(boolean enabled) {
- mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED,
- enabled ? 1 : 0, 0).sendToTarget();
+ public void setState(int state) {
+ mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget();
}
};
@@ -119,14 +118,8 @@
@Override
public void handleMessage(Message message) {
switch (message.what) {
- case DO_SET_ACCESSIBILITY_ENABLED :
- final boolean isAccessibilityEnabled = (message.arg1 == 1);
- setAccessibilityState(isAccessibilityEnabled);
- return;
- case DO_SET_TOUCH_EXPLORATION_ENABLED :
- synchronized (mHandler) {
- mIsTouchExplorationEnabled = (message.arg1 == 1);
- }
+ case DO_SET_STATE :
+ setState(message.arg1);
return;
default :
Log.w(LOG_TAG, "Unknown message type: " + message.what);
@@ -163,8 +156,8 @@
mService = service;
try {
- final boolean isEnabled = mService.addClient(mClient);
- setAccessibilityState(isEnabled);
+ final int stateFlags = mService.addClient(mClient);
+ setState(stateFlags);
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
}
@@ -341,6 +334,17 @@
}
/**
+ * Sets the current state.
+ *
+ * @param stateFlags The state flags.
+ */
+ private void setState(int stateFlags) {
+ final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+ setAccessibilityState(accessibilityEnabled);
+ mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
+ }
+
+ /**
* Sets the enabled state.
*
* @param isEnabled The accessibility state.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 0e04471..6469b35 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -294,14 +294,14 @@
}
/**
- * Gets the unique id identifying this node's parent.
+ * Gets the parent.
* <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>
*
- * @return The node's patent id.
+ * @return The parent.
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index b14f02a..c621ff6 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -34,7 +34,7 @@
*/
interface IAccessibilityManager {
- boolean addClient(IAccessibilityManagerClient client);
+ int addClient(IAccessibilityManagerClient client);
boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 4e69692..5e7e813 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -24,7 +24,5 @@
*/
oneway interface IAccessibilityManagerClient {
- void setEnabled(boolean enabled);
-
- void setTouchExplorationEnabled(boolean enabled);
+ void setState(int stateFlags);
}
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 229b414..ae253cf 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -22,9 +22,9 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.view.textservice.SpellCheckerInfo;
import android.service.textservice.SpellCheckerSession;
import android.service.textservice.SpellCheckerSession.SpellCheckerSessionListener;
+import android.util.Log;
import java.util.Locale;
@@ -38,6 +38,7 @@
*/
public final class TextServicesManager {
private static final String TAG = TextServicesManager.class.getSimpleName();
+ private static final boolean DBG = false;
private static TextServicesManager sInstance;
private static ITextServicesManager sService;
@@ -75,12 +76,14 @@
// TODO: Handle referToSpellCheckerLanguageSettings
public SpellCheckerSession newSpellCheckerSession(Locale locale,
SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
- if (locale == null || listener == null) {
+ if (listener == null) {
throw new NullPointerException();
}
+ // TODO: set a proper locale instead of the dummy locale
+ final String localeString = locale == null ? "en" : locale.toString();
final SpellCheckerInfo info;
try {
- info = sService.getCurrentSpellChecker(locale.toString());
+ info = sService.getCurrentSpellChecker(localeString);
} catch (RemoteException e) {
return null;
}
@@ -89,8 +92,8 @@
}
final SpellCheckerSession session = new SpellCheckerSession(info, sService, listener);
try {
- sService.getSpellCheckerService(
- info, locale.toString(), session.getTextServicesSessionListener(),
+ sService.getSpellCheckerService(info, localeString,
+ session.getTextServicesSessionListener(),
session.getSpellCheckerSessionListener());
} catch (RemoteException e) {
return null;
@@ -103,8 +106,13 @@
*/
public SpellCheckerInfo[] getEnabledSpellCheckers() {
try {
- return sService.getEnabledSpellCheckers();
+ final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers();
+ if (DBG) {
+ Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
+ }
+ return retval;
} catch (RemoteException e) {
+ Log.e(TAG, "Error in getEnabledSpellCheckers: " + e);
return null;
}
}
diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java
index 3cb5e24..a21d3ee 100644
--- a/core/java/android/webkit/DebugFlags.java
+++ b/core/java/android/webkit/DebugFlags.java
@@ -47,7 +47,7 @@
public static final boolean WEB_VIEW_CORE = false;
/*
* Set to true to allow the WebTextView to draw on top of the web page in a
- * different color so that you can see how the two line up.
+ * different color with no background so you can see how the two line up.
*/
public static final boolean DRAW_WEBTEXTVIEW = false;
}
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index bb4d192..620973e 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.net.Uri;
+import android.provider.Settings;
import android.util.Log;
import java.io.InputStream;
@@ -38,7 +39,7 @@
private static boolean initialized = false;
- private static void checkIntialized() {
+ private static void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class");
}
@@ -63,7 +64,7 @@
* @return String The application's database directory
*/
private static synchronized String getDatabaseDirectory() {
- checkIntialized();
+ checkInitialized();
if (sDatabaseDirectory == null)
sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent();
@@ -76,7 +77,7 @@
* @return String The application's cache directory
*/
private static synchronized String getCacheDirectory() {
- checkIntialized();
+ checkInitialized();
if (sCacheDirectory == null)
sCacheDirectory = sContext.getCacheDir().getAbsolutePath();
@@ -166,5 +167,13 @@
return sUseChromiumHttpStack;
}
+ private static synchronized String getAutofillQueryUrl() {
+ checkInitialized();
+ // If the device has not checked in it won't have pulled down the system setting for the
+ // Autofill Url. In that case we will not make autofill server requests.
+ return Settings.Secure.getString(sContext.getContentResolver(),
+ Settings.Secure.WEB_AUTOFILL_QUERY_URL);
+ }
+
private static native boolean nativeUseChromiumHttpStack();
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index d54230c..b8c4e22 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -25,7 +25,7 @@
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -87,7 +87,6 @@
// Keep track of the text before the change so we know whether we actually
// need to send down the DOM events.
private String mPreChange;
- private Drawable mBackground;
// Variables for keeping track of the touch down, to send to the WebView
// when a drag starts
private float mDragStartX;
@@ -190,6 +189,8 @@
// that other applications that use embedded WebViews will properly
// display the text in password textfields.
setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
+ setBackgroundDrawable(DebugFlags.DRAW_WEBTEXTVIEW ? null : new ColorDrawable(Color.WHITE));
+
// This helps to align the text better with the text in the web page.
setIncludeFontPadding(false);
@@ -423,24 +424,6 @@
// makeNewLayout does.
super.makeNewLayout(w, hintWidth, boring, hintBoring, ellipsisWidth,
bringIntoView);
-
- // For fields that do not draw, create a layout which is altered so that
- // the text lines up.
- if (DebugFlags.DRAW_WEBTEXTVIEW || willNotDraw()) {
- float lineHeight = -1;
- if (mWebView != null) {
- float height = mWebView.nativeFocusCandidateLineHeight();
- if (height != -1) {
- lineHeight = height * mWebView.getScale();
- }
- }
- CharSequence text = getText();
- // Copy from the existing Layout.
- mLayout = new WebTextViewLayout(text, text, getPaint(), mLayout.getWidth(),
- mLayout.getAlignment(), mLayout.getSpacingMultiplier(),
- mLayout.getSpacingAdd(), false, null, ellipsisWidth,
- lineHeight);
- }
lineUpScroll();
}
@@ -491,51 +474,6 @@
return connection;
}
- /**
- * In general, TextView makes a call to InputMethodManager.updateSelection
- * in onDraw. However, in the general case of WebTextView, we do not draw.
- * This method is called by WebView.onDraw to take care of the part that
- * needs to be called.
- */
- /* package */ void onDrawSubstitute() {
- if (!willNotDraw()) {
- // If the WebTextView is set to draw, such as in the case of a
- // password, onDraw calls updateSelection(), so this code path is
- // unnecessary.
- return;
- }
- // This code is copied from TextView.onDraw(). That code does not get
- // executed, however, because the WebTextView does not draw, allowing
- // webkit's drawing to show through.
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null && imm.isActive(this)) {
- Spannable sp = (Spannable) getText();
- int selStart = Selection.getSelectionStart(sp);
- int selEnd = Selection.getSelectionEnd(sp);
- int candStart = EditableInputConnection.getComposingSpanStart(sp);
- int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
- imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- // onDraw should only be called for password fields. If WebTextView is
- // still drawing, but is no longer corresponding to a password field,
- // remove it.
- if (!DebugFlags.DRAW_WEBTEXTVIEW && (mWebView == null
- || !mWebView.nativeFocusCandidateIsPassword()
- || !isSameTextField(mWebView.nativeFocusCandidatePointer()))) {
- // Although calling remove() would seem to make more sense here,
- // changing it to not be a password field will make it not draw.
- // Other code will make sure that it is removed completely, but this
- // way the user will not see it.
- setInPassword(false);
- } else {
- super.onDraw(canvas);
- }
- }
-
@Override
public void onEditorAction(int actionCode) {
switch (actionCode) {
@@ -928,102 +866,6 @@
if (mWebView != null) mWebView.incrementTextGeneration();
}
- /**
- * Determine whether to use the system-wide password disguising method,
- * or to use none.
- * @param inPassword True if the textfield is a password field.
- */
- /* package */ void setInPassword(boolean inPassword) {
- if (inPassword) {
- setInputType(InputType.TYPE_CLASS_TEXT | EditorInfo.
- TYPE_TEXT_VARIATION_WEB_PASSWORD);
- createBackground();
- }
- // For password fields, draw the WebTextView. For others, just show
- // webkit's drawing.
- if (!DebugFlags.DRAW_WEBTEXTVIEW) {
- setWillNotDraw(!inPassword);
- }
- setBackgroundDrawable(inPassword ? mBackground : null);
- }
-
- /**
- * Private class used for the background of a password textfield.
- */
- private static class OutlineDrawable extends Drawable {
- private Paint mBackgroundPaint;
- private Paint mOutlinePaint;
- private float[] mLines;
- public OutlineDrawable() {
- mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mBackgroundPaint.setColor(Color.WHITE);
-
- mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mOutlinePaint.setColor(Color.BLACK);
- mOutlinePaint.setStyle(Paint.Style.STROKE);
-
- mLines = new float[16];
- }
- @Override
- public void setBounds(int left, int top, int right, int bottom) {
- super.setBounds(left, top, right, bottom);
- bottom--;
- right -= 2;
- // Top line
- mLines[0] = left;
- mLines[1] = top + 1;
- mLines[2] = right;
- mLines[3] = top + 1;
- // Right line
- mLines[4] = right;
- mLines[5] = top;
- mLines[6] = right;
- mLines[7] = bottom;
- // Bottom line
- mLines[8] = left;
- mLines[9] = bottom;
- mLines[10] = right;
- mLines[11] = bottom;
- // Left line
- mLines[12] = left + 1;
- mLines[13] = top;
- mLines[14] = left + 1;
- mLines[15] = bottom;
- }
- @Override
- public void draw(Canvas canvas) {
- // Draw the background.
- canvas.drawRect(getBounds(), mBackgroundPaint);
- // Draw the outline.
- canvas.drawLines(mLines, mOutlinePaint);
- }
- // Always want it to be opaque.
- @Override
- public int getOpacity() {
- return PixelFormat.OPAQUE;
- }
- // These are needed because they are abstract in Drawable.
- @Override
- public void setAlpha(int alpha) { }
- @Override
- public void setColorFilter(ColorFilter cf) { }
- }
-
- /**
- * Create a background for the WebTextView and set up the paint for drawing
- * the text. This way, we can see the password transformation of the
- * system, which (optionally) shows the actual text before changing to dots.
- * The background is necessary to hide the webkit-drawn text beneath.
- */
- private void createBackground() {
- if (mBackground != null) {
- return;
- }
- mBackground = new OutlineDrawable();
-
- setGravity(Gravity.CENTER_VERTICAL);
- }
-
@Override
public void setInputType(int type) {
mFromSetInputType = true;
@@ -1072,7 +914,8 @@
lp.height = height;
}
if (getParent() == null) {
- mWebView.addView(this, lp);
+ // Insert the view so that it's drawn first (at index 0)
+ mWebView.addView(this, 0, lp);
} else {
setLayoutParams(lp);
}
@@ -1145,7 +988,6 @@
/* package */ void setType(int type) {
if (mWebView == null) return;
boolean single = true;
- boolean inPassword = false;
int maxLength = -1;
int inputType = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
@@ -1167,7 +1009,7 @@
imeOptions |= EditorInfo.IME_ACTION_NONE;
break;
case PASSWORD:
- inPassword = true;
+ inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
imeOptions |= EditorInfo.IME_ACTION_GO;
break;
case SEARCH:
@@ -1219,7 +1061,7 @@
setHorizontallyScrolling(single);
setInputType(inputType);
setImeOptions(imeOptions);
- setInPassword(inPassword);
+ setVisibility(VISIBLE);
AutoCompleteAdapter adapter = null;
setAdapterCustom(adapter);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6a3b2ff..5946ae4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2285,7 +2285,7 @@
checkThread();
mContentWidth = 0;
mContentHeight = 0;
- setBaseLayer(0, null, false, false);
+ setBaseLayer(0, null, false, false, false);
mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
@@ -4068,9 +4068,6 @@
if (AUTO_REDRAW_HACK && mAutoRedraw) {
invalidate();
}
- if (inEditingMode()) {
- mWebTextView.onDrawSubstitute();
- }
mWebViewCore.signalRepaintDone();
if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas)) {
@@ -4271,11 +4268,11 @@
}
void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
- boolean isPictureAfterFirstLayout) {
+ boolean isPictureAfterFirstLayout, boolean registerPageSwapCallback) {
if (mNativeClass == 0)
return;
nativeSetBaseLayer(layer, invalRegion, showVisualIndicator,
- isPictureAfterFirstLayout);
+ isPictureAfterFirstLayout, registerPageSwapCallback);
if (mHTML5VideoViewProxy != null) {
mHTML5VideoViewProxy.setBaseLayer(layer);
}
@@ -4287,18 +4284,18 @@
private void onZoomAnimationStart() {
// If it is in password mode, turn it off so it does not draw misplaced.
- if (inEditingMode() && nativeFocusCandidateIsPassword()) {
- mWebTextView.setInPassword(false);
+ if (inEditingMode()) {
+ mWebTextView.setVisibility(INVISIBLE);
}
}
private void onZoomAnimationEnd() {
// adjust the edit text view if needed
- if (inEditingMode() && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)
- && nativeFocusCandidateIsPassword()) {
+ if (inEditingMode()
+ && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)) {
// If it is a password field, start drawing the WebTextView once
// again.
- mWebTextView.setInPassword(true);
+ mWebTextView.setVisibility(VISIBLE);
}
}
@@ -4423,8 +4420,9 @@
mFocusSizeChanged = false;
// If we are zooming, this will get handled above, when the zoom
// finishes. We also do not need to do this unless the WebTextView
- // is showing.
- if (!animateZoom && inEditingMode()) {
+ // is showing. With hardware acceleration, the pageSwapCallback()
+ // updates the WebTextView position in sync with page swapping
+ if (!canvas.isHardwareAccelerated() && !animateZoom && inEditingMode()) {
didUpdateWebTextViewDimensions(ANYWHERE);
}
}
@@ -4593,37 +4591,23 @@
}
String text = nativeFocusCandidateText();
int nodePointer = nativeFocusCandidatePointer();
- if (alreadyThere && mWebTextView.isSameTextField(nodePointer)) {
- // It is possible that we have the same textfield, but it has moved,
- // i.e. In the case of opening/closing the screen.
- // In that case, we need to set the dimensions, but not the other
- // aspects.
- // If the text has been changed by webkit, update it. However, if
- // there has been more UI text input, ignore it. We will receive
- // another update when that text is recognized.
- if (text != null && !text.equals(mWebTextView.getText().toString())
- && nativeTextGeneration() == mTextGeneration) {
- mWebTextView.setTextAndKeepSelection(text);
+ mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
+ Gravity.RIGHT : Gravity.NO_GRAVITY);
+ // This needs to be called before setType, which may call
+ // requestFormData, and it needs to have the correct nodePointer.
+ mWebTextView.setNodePointer(nodePointer);
+ mWebTextView.setType(nativeFocusCandidateType());
+ updateWebTextViewPadding();
+ if (null == text) {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "rebuildWebTextView null == text");
}
- } else {
- mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
- Gravity.RIGHT : Gravity.NO_GRAVITY);
- // This needs to be called before setType, which may call
- // requestFormData, and it needs to have the correct nodePointer.
- mWebTextView.setNodePointer(nodePointer);
- mWebTextView.setType(nativeFocusCandidateType());
- updateWebTextViewPadding();
- if (null == text) {
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "rebuildWebTextView null == text");
- }
- text = "";
- }
- mWebTextView.setTextAndKeepSelection(text);
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null && imm.isActive(mWebTextView)) {
- imm.restartInput(mWebTextView);
- }
+ text = "";
+ }
+ mWebTextView.setTextAndKeepSelection(text);
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && imm.isActive(mWebTextView)) {
+ imm.restartInput(mWebTextView);
}
if (isFocused()) {
mWebTextView.requestFocus();
@@ -4701,6 +4685,7 @@
private Message mUpdateMessage;
private boolean mAutoFillable;
private boolean mAutoComplete;
+ private WebSettings mWebSettings;
public RequestFormData(String name, String url, Message msg,
boolean autoFillable, boolean autoComplete) {
@@ -4709,6 +4694,7 @@
mUpdateMessage = msg;
mAutoFillable = autoFillable;
mAutoComplete = autoComplete;
+ mWebSettings = getSettings();
}
public void run() {
@@ -4718,8 +4704,7 @@
// Note that code inside the adapter click handler in WebTextView depends
// on the AutoFill item being at the top of the drop down list. If you change
// the order, make sure to do it there too!
- WebSettings settings = getSettings();
- if (settings != null && settings.getAutoFillProfile() != null) {
+ if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) {
pastEntries.add(getResources().getText(
com.android.internal.R.string.autofill_this_form).toString() +
" " +
@@ -8119,19 +8104,7 @@
// and representing the same node as the pointer.
if (inEditingMode() &&
mWebTextView.isSameTextField(msg.arg1)) {
- if (msg.getData().getBoolean("password")) {
- Spannable text = (Spannable) mWebTextView.getText();
- int start = Selection.getSelectionStart(text);
- int end = Selection.getSelectionEnd(text);
- mWebTextView.setInPassword(true);
- // Restore the selection, which may have been
- // ruined by setInPassword.
- Spannable pword =
- (Spannable) mWebTextView.getText();
- Selection.setSelection(pword, start, end);
- // If the text entry has created more events, ignore
- // this one.
- } else if (msg.arg2 == mTextGeneration) {
+ if (msg.arg2 == mTextGeneration) {
String text = (String) msg.obj;
if (null == text) {
text = "";
@@ -8423,6 +8396,14 @@
}
}
+ // Called by JNI to invalidate the View, given rectangle coordinates in
+ // content space
+ private void pageSwapCallback() {
+ if (inEditingMode()) {
+ didUpdateWebTextViewDimensions(ANYWHERE);
+ }
+ }
+
void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
if (mNativeClass == 0) {
if (mDelaySetPicture != null) {
@@ -8435,10 +8416,15 @@
}
WebViewCore.ViewState viewState = draw.mViewState;
boolean isPictureAfterFirstLayout = viewState != null;
+
+ // Request a callback on pageSwap (to reposition the webtextview)
+ boolean registerPageSwapCallback =
+ !mZoomManager.isFixedLengthAnimationInProgress() && inEditingMode();
+
if (updateBaseLayer) {
setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
getSettings().getShowVisualIndicator(),
- isPictureAfterFirstLayout);
+ isPictureAfterFirstLayout, registerPageSwapCallback);
}
final Point viewSize = draw.mViewSize;
if (isPictureAfterFirstLayout) {
@@ -9237,7 +9223,8 @@
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetHeightCanMeasure(boolean measure);
private native void nativeSetBaseLayer(int layer, Region invalRegion,
- boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
+ boolean showVisualIndicator, boolean isPictureAfterFirstLayout,
+ boolean registerPageSwapCallback);
private native int nativeGetBaseLayer();
private native void nativeShowCursorTimed();
private native void nativeReplaceBaseContent(int content);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b7c1687..cadf2ab 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -261,6 +261,11 @@
private RemoteViewsAdapter mRemoteAdapter;
/**
+ * This flag indicates the a full notify is required when the RemoteViewsAdapter connects
+ */
+ private boolean mDeferNotifyDataSetChanged = false;
+
+ /**
* Indicates whether the list selector should be drawn on top of the children or behind
*/
boolean mDrawSelectorOnTop = false;
@@ -2817,9 +2822,11 @@
mPositionScroller.stop();
}
mTouchMode = TOUCH_MODE_OVERSCROLL;
+ mMotionX = (int) ev.getX();
mMotionY = mLastY = (int) ev.getY();
mMotionCorrection = 0;
mActivePointerId = ev.getPointerId(0);
+ mDirection = 0;
break;
}
@@ -2994,9 +3001,38 @@
mDirection = newDirection;
}
- if (mDirection != newDirection) {
+ int overScrollDistance = -incrementalDeltaY;
+ if ((newScroll < 0 && oldScroll >= 0) || (newScroll > 0 && oldScroll <= 0)) {
+ overScrollDistance = -oldScroll;
+ incrementalDeltaY += overScrollDistance;
+ } else {
+ incrementalDeltaY = 0;
+ }
+
+ if (overScrollDistance != 0) {
+ overScrollBy(0, overScrollDistance, 0, mScrollY, 0, 0,
+ 0, mOverscrollDistance, true);
+ final int overscrollMode = getOverScrollMode();
+ if (overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
+ !contentFits())) {
+ if (rawDeltaY > 0) {
+ mEdgeGlowTop.onPull((float) overScrollDistance / getHeight());
+ if (!mEdgeGlowBottom.isFinished()) {
+ mEdgeGlowBottom.onRelease();
+ }
+ } else if (rawDeltaY < 0) {
+ mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight());
+ if (!mEdgeGlowTop.isFinished()) {
+ mEdgeGlowTop.onRelease();
+ }
+ }
+ invalidate();
+ }
+ }
+
+ if (incrementalDeltaY != 0) {
// Coming back to 'real' list scrolling
- incrementalDeltaY = -newScroll;
mScrollY = 0;
invalidateParentIfNeeded();
@@ -3005,45 +3041,17 @@
trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
}
- // Check to see if we are back in
- View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
- if (motionView != null) {
- mTouchMode = TOUCH_MODE_SCROLL;
+ mTouchMode = TOUCH_MODE_SCROLL;
- // We did not scroll the full amount. Treat this essentially like the
- // start of a new touch scroll
- final int motionPosition = findClosestMotionRow(y);
+ // We did not scroll the full amount. Treat this essentially like the
+ // start of a new touch scroll
+ final int motionPosition = findClosestMotionRow(y);
- mMotionCorrection = 0;
- motionView = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = motionView.getTop();
- mMotionY = y;
- mMotionPosition = motionPosition;
- }
- } else {
- overScrollBy(0, -incrementalDeltaY, 0, mScrollY, 0, 0,
- 0, mOverscrollDistance, true);
- final int overscrollMode = getOverScrollMode();
- if (overscrollMode == OVER_SCROLL_ALWAYS ||
- (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
- !contentFits())) {
- if (rawDeltaY > 0) {
- mEdgeGlowTop.onPull((float) -incrementalDeltaY / getHeight());
- if (!mEdgeGlowBottom.isFinished()) {
- mEdgeGlowBottom.onRelease();
- }
- } else if (rawDeltaY < 0) {
- mEdgeGlowBottom.onPull((float) -incrementalDeltaY / getHeight());
- if (!mEdgeGlowTop.isFinished()) {
- mEdgeGlowTop.onRelease();
- }
- }
- invalidate();
- }
- if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
- // Don't allow overfling if we're at the edge.
- mVelocityTracker.clear();
- }
+ mMotionCorrection = 0;
+ View motionView = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = motionView != null ? motionView.getTop() : 0;
+ mMotionY = y;
+ mMotionPosition = motionPosition;
}
mLastY = y;
mDirection = newDirection;
@@ -3320,12 +3328,6 @@
mScrollY = scrollY;
invalidateParentIfNeeded();
- if (clampedY) {
- // Velocity is broken by hitting the limit; don't start a fling off of this.
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
- }
- }
awakenScrollBars();
}
}
@@ -3616,9 +3618,8 @@
}
void startOverfling(int initialVelocity) {
- final int min = mScrollY > 0 ? Integer.MIN_VALUE : 0;
- final int max = mScrollY > 0 ? 0 : Integer.MAX_VALUE;
- mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, min, max, 0, getHeight());
+ mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0,
+ Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight());
mTouchMode = TOUCH_MODE_OVERFLING;
invalidate();
post(this);
@@ -3768,10 +3769,22 @@
final OverScroller scroller = mScroller;
if (scroller.computeScrollOffset()) {
final int scrollY = mScrollY;
- final int deltaY = scroller.getCurrY() - scrollY;
+ final int currY = scroller.getCurrY();
+ final int deltaY = currY - scrollY;
if (overScrollBy(0, deltaY, 0, scrollY, 0, 0,
0, mOverflingDistance, false)) {
- startSpringback();
+ final boolean crossDown = scrollY <= 0 && currY > 0;
+ final boolean crossUp = scrollY >= 0 && currY < 0;
+ if (crossDown || crossUp) {
+ int velocity = (int) scroller.getCurrVelocity();
+ if (crossUp) velocity = -velocity;
+
+ // Don't flywheel from this; we're just continuing things.
+ scroller.abortAnimation();
+ start(velocity);
+ } else {
+ startSpringback();
+ }
} else {
invalidate();
post(this);
@@ -5384,17 +5397,29 @@
return;
}
}
-
+ mDeferNotifyDataSetChanged = false;
// Otherwise, create a new RemoteViewsAdapter for binding
mRemoteAdapter = new RemoteViewsAdapter(getContext(), intent, this);
}
/**
+ * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
+ * connected yet.
+ */
+ public void deferNotifyDataSetChanged() {
+ mDeferNotifyDataSetChanged = true;
+ }
+
+ /**
* Called back when the adapter connects to the RemoteViewsService.
*/
public boolean onRemoteAdapterConnected() {
if (mRemoteAdapter != mAdapter) {
setAdapter(mRemoteAdapter);
+ if (mDeferNotifyDataSetChanged) {
+ mRemoteAdapter.notifyDataSetChanged();
+ mDeferNotifyDataSetChanged = false;
+ }
return false;
} else if (mRemoteAdapter != null) {
mRemoteAdapter.superNotifyDataSetChanged();
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index d85f8a4..45d73af 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -29,16 +29,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ActivityChooserModel;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListPopupWindow;
-import android.widget.PopupWindow;
-import android.widget.TextView;
import com.android.internal.R;
@@ -85,12 +76,22 @@
/**
* The expand activities action button;
*/
- private final ImageButton mExpandActivityOverflowButton;
+ private final FrameLayout mExpandActivityOverflowButton;
+
+ /**
+ * The image for the expand activities action button;
+ */
+ private final ImageView mExpandActivityOverflowButtonImage;
/**
* The default activities action button;
*/
- private final ImageButton mDefaultActionButton;
+ private final FrameLayout mDefaultActivityButton;
+
+ /**
+ * The image for the default activities action button;
+ */
+ private final ImageView mDefaultActivityButtonImage;
/**
* The maximal width of the list popup.
@@ -185,13 +186,16 @@
mActivityChooserContent = (LinearLayout) findViewById(R.id.activity_chooser_view_content);
- mDefaultActionButton = (ImageButton) findViewById(R.id.default_activity_button);
- mDefaultActionButton.setOnClickListener(mCallbacks);
- mDefaultActionButton.setOnLongClickListener(mCallbacks);
+ mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
+ mDefaultActivityButton.setOnClickListener(mCallbacks);
+ mDefaultActivityButton.setOnLongClickListener(mCallbacks);
+ mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
- mExpandActivityOverflowButton = (ImageButton) findViewById(R.id.expand_activities_button);
+ mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.expand_activities_button);
mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
- mExpandActivityOverflowButton.setImageDrawable(expandActivityOverflowButtonDrawable);
+ mExpandActivityOverflowButtonImage =
+ (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image);
+ mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
mAdapter = new ActivityChooserViewAdapter();
mAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -230,7 +234,7 @@
* @param drawable The drawable.
*/
public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
- mExpandActivityOverflowButton.setImageDrawable(drawable);
+ mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
}
/**
@@ -391,7 +395,7 @@
private void updateButtons() {
final int activityCount = mAdapter.getActivityCount();
if (activityCount > 0) {
- mDefaultActionButton.setVisibility(VISIBLE);
+ mDefaultActivityButton.setVisibility(VISIBLE);
if (mAdapter.getCount() > 0) {
mExpandActivityOverflowButton.setEnabled(true);
} else {
@@ -399,9 +403,9 @@
}
ResolveInfo activity = mAdapter.getDefaultActivity();
PackageManager packageManager = mContext.getPackageManager();
- mDefaultActionButton.setImageDrawable(activity.loadIcon(packageManager));
+ mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
} else {
- mDefaultActionButton.setVisibility(View.INVISIBLE);
+ mDefaultActivityButton.setVisibility(View.INVISIBLE);
mExpandActivityOverflowButton.setEnabled(false);
}
}
@@ -440,7 +444,7 @@
// View.OnClickListener
public void onClick(View view) {
- if (view == mDefaultActionButton) {
+ if (view == mDefaultActivityButton) {
dismissPopup();
ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
@@ -457,7 +461,7 @@
// OnLongClickListener#onLongClick
@Override
public boolean onLongClick(View view) {
- if (view == mDefaultActionButton) {
+ if (view == mDefaultActivityButton) {
if (mAdapter.getCount() > 0) {
mIsSelectingDefaultActivity = true;
showPopupUnchecked(mInitialActivityCount);
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index c773527..c83c780 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -16,16 +16,12 @@
package android.widget;
-import java.util.ArrayList;
-import java.util.HashMap;
-
import android.animation.AnimatorInflater;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.os.Handler;
-import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -34,6 +30,9 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import java.util.ArrayList;
+import java.util.HashMap;
+
/**
* Base class for a {@link AdapterView} that will perform animations
* when switching between its views.
@@ -118,6 +117,11 @@
RemoteViewsAdapter mRemoteViewsAdapter;
/**
+ * The remote adapter containing the data to be displayed by this view to be set
+ */
+ boolean mDeferNotifyDataSetChanged = false;
+
+ /**
* Specifies whether this is the first time the animator is showing views
*/
boolean mFirstTime = true;
@@ -966,7 +970,7 @@
return;
}
}
-
+ mDeferNotifyDataSetChanged = false;
// Otherwise, create a new RemoteViewsAdapter for binding
mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
}
@@ -982,12 +986,25 @@
}
/**
+ * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
+ * connected yet.
+ */
+ public void deferNotifyDataSetChanged() {
+ mDeferNotifyDataSetChanged = true;
+ }
+
+ /**
* Called back when the adapter connects to the RemoteViewsService.
*/
public boolean onRemoteAdapterConnected() {
if (mRemoteViewsAdapter != mAdapter) {
setAdapter(mRemoteViewsAdapter);
+ if (mDeferNotifyDataSetChanged) {
+ mRemoteViewsAdapter.notifyDataSetChanged();
+ mDeferNotifyDataSetChanged = false;
+ }
+
// Restore the previous position (see onRestoreInstanceState)
if (mRestoreWhichChild > -1) {
setDisplayedChild(mRestoreWhichChild, false);
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 273c258..4419886 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -62,15 +62,14 @@
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.ViewFlipper);
+ com.android.internal.R.styleable.AdapterViewFlipper);
mFlipInterval = a.getInt(
- com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
+ com.android.internal.R.styleable.AdapterViewFlipper_flipInterval, DEFAULT_INTERVAL);
mAutoStart = a.getBoolean(
- com.android.internal.R.styleable.ViewFlipper_autoStart, false);
+ com.android.internal.R.styleable.AdapterViewFlipper_autoStart, false);
- // By default we want the flipper to loop
- mLoopViews = a.getBoolean(
- com.android.internal.R.styleable.AdapterViewAnimator_loopViews, true);
+ // A view flipper should cycle through the views
+ mLoopViews = true;
a.recycle();
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 5eba1a0..0b0b812 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -34,12 +34,17 @@
/**
* FrameLayout is designed to block out an area on the screen to display
- * a single item. You can add multiple children to a FrameLayout and control their
- * position within the FrameLayout using {@link android.widget.FrameLayout.LayoutParams#gravity}.
- * Children are drawn in a stack, with the most recently added child on top.
- * The size of the frame layout is the size of its largest child (plus padding), visible
- * or not (if the FrameLayout's parent permits). Views that are GONE are used for sizing
- * only if {@link #setMeasureAllChildren(boolean) setMeasureAllChildren()}
+ * a single item. Generally, FrameLayout should be used to hold a single child view, because it can
+ * be difficult to organize child views in a way that's scalable to different screen sizes without
+ * the children overlapping each other. You can, however, add multiple children to a FrameLayout
+ * and control their position within the FrameLayout by assigning gravity to each child, using the
+ * <a href="FrameLayout.LayoutParams.html#attr_android:layout_gravity">{@code
+ * android:layout_gravity}</a> attribute.
+ * <p>Child views are drawn in a stack, with the most recently added child on top.
+ * The size of the FrameLayout is the size of its largest child (plus padding), visible
+ * or not (if the FrameLayout's parent permits). Views that are {@link android.view.View#GONE} are
+ * used for sizing
+ * only if {@link #setMeasureAllChildren(boolean) setConsiderGoneChildrenWhenMeasuring()}
* is set to true.
*
* @attr ref android.R.styleable#FrameLayout_foreground
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 3bd7fab..f999960 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -21,7 +21,6 @@
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
@@ -38,6 +37,7 @@
import java.util.List;
import java.util.Map;
+import static android.view.Gravity.*;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -167,7 +167,7 @@
// Misc constants
private static final String TAG = GridLayout.class.getName();
- static boolean DEBUG = false;
+ private static boolean DEBUG = false;
private static final int PRF = 1;
// Defaults
@@ -198,7 +198,8 @@
private int mOrientation = DEFAULT_ORIENTATION;
private boolean mUseDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
private int mAlignmentMode = DEFAULT_ALIGNMENT_MODE;
- private int mDefaultGravity = Gravity.NO_GRAVITY;
+ private Alignment mColumnAlignment = LEFT;
+ private Alignment mRowAlignment = BASELINE;
private int mDefaultGap;
// Constructors
@@ -216,9 +217,9 @@
try {
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);
- mAlignmentMode = a.getInt(ALIGNMENT_MODE, DEFAULT_ALIGNMENT_MODE);
+ setOrientation(a.getInt(ORIENTATION, DEFAULT_ORIENTATION));
+ setUseDefaultMargins(a.getBoolean(USE_DEFAULT_MARGINS, DEFAULT_USE_DEFAULT_MARGINS));
+ setAlignmentMode(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 {
@@ -514,6 +515,8 @@
requestLayout();
}
+ // Static utility methods
+
private static int max2(int[] a, int valueIfEmpty) {
int result = valueIfEmpty;
for (int i = 0, N = a.length; i < N; i++) {
@@ -537,6 +540,24 @@
return result;
}
+ private static Alignment getAlignment(int gravity, boolean horizontal) {
+ int mask = horizontal ? HORIZONTAL_GRAVITY_MASK : VERTICAL_GRAVITY_MASK;
+ int shift = horizontal ? AXIS_X_SHIFT : AXIS_Y_SHIFT;
+ int flags = (gravity & mask) >> shift;
+ switch (flags) {
+ case (AXIS_SPECIFIED | AXIS_PULL_BEFORE):
+ return LEADING;
+ case (AXIS_SPECIFIED | AXIS_PULL_AFTER):
+ return TRAILING;
+ case (AXIS_SPECIFIED | AXIS_PULL_BEFORE | AXIS_PULL_AFTER):
+ return FILL;
+ case AXIS_SPECIFIED:
+ return CENTER;
+ default:
+ return UNDEFINED_ALIGNMENT;
+ }
+ }
+
private int getDefaultMargin(View c, boolean horizontal, boolean leading) {
return mDefaultGap / 2;
}
@@ -678,7 +699,7 @@
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs, mDefaultGravity);
+ return new LayoutParams(getContext(), attrs);
}
@Override
@@ -833,6 +854,9 @@
}
private int getMeasurementIncludingMargin(View c, boolean horizontal) {
+ if (isGone(c)) {
+ return 0;
+ }
int result = getMeasurement(c, horizontal);
if (mAlignmentMode == ALIGN_MARGINS) {
return result + getTotalMargin(c, horizontal);
@@ -846,6 +870,11 @@
invalidateValues();
}
+ private Alignment getAlignment(Alignment alignment, boolean horizontal) {
+ return (alignment != UNDEFINED_ALIGNMENT) ? alignment :
+ (horizontal ? mColumnAlignment : mRowAlignment);
+ }
+
// Layout container
/**
@@ -895,8 +924,8 @@
int pWidth = getMeasurement(c, true);
int pHeight = getMeasurement(c, false);
- Alignment hAlign = columnSpec.alignment;
- Alignment vAlign = rowSpec.alignment;
+ Alignment hAlign = getAlignment(columnSpec.alignment, true);
+ Alignment vAlign = getAlignment(rowSpec.alignment, false);
int dx, dy;
@@ -1035,14 +1064,10 @@
Assoc<Spec, Bounds> assoc = Assoc.of(Spec.class, Bounds.class);
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (isGone(c)) {
- assoc.put(Spec.GONE, Bounds.GONE);
- } else {
- LayoutParams lp = getLayoutParams(c);
- Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
- Bounds bounds = spec.alignment.getBounds();
- assoc.put(spec, bounds);
- }
+ LayoutParams lp = getLayoutParams(c);
+ Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
+ Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds();
+ assoc.put(spec, bounds);
}
return assoc.pack();
}
@@ -1054,7 +1079,6 @@
}
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
- if (isGone(c)) continue;
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
groupBounds.getValue(i).include(c, spec, GridLayout.this, this);
@@ -1094,11 +1118,8 @@
for (int i = 0; i < bounds.length; i++) {
int size = bounds[i].size(min);
MutableInt valueHolder = links.getValue(i);
- if (min) {
- valueHolder.value = max(valueHolder.value, size);
- } else {
- valueHolder.value = -max(-valueHolder.value, size);
- }
+ // this effectively takes the max() of the minima and the min() of the maxima
+ valueHolder.value = max(valueHolder.value, min ? size : -size);
}
}
@@ -1397,7 +1418,7 @@
}
if (!changed) {
if (DEBUG) {
- Log.d(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N);
+ Log.v(TAG, axis + " iteration completed in " + (1 + i) + " steps of " + N);
}
return;
}
@@ -1654,14 +1675,6 @@
private static final int DEFAULT_COLUMN = UNDEFINED;
private static final Interval DEFAULT_SPAN = new Interval(UNDEFINED, UNDEFINED + 1);
private static final int DEFAULT_SPAN_SIZE = DEFAULT_SPAN.size();
- private static final Alignment DEFAULT_COLUMN_ALIGNMENT = LEFT;
- private static final Alignment DEFAULT_ROW_ALIGNMENT = BASELINE;
-
- // Misc
-
- private static final Rect CONTAINER_BOUNDS = new Rect(0, 0, 2, 2);
- private static final Alignment[] COLUMN_ALIGNMENTS = { LEFT, CENTER, RIGHT };
- private static final Alignment[] ROW_ALIGNMENTS = { TOP, CENTER, BOTTOM };
// TypedArray indices
@@ -1728,8 +1741,7 @@
* Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
*/
public LayoutParams() {
- this(new Spec(DEFAULT_SPAN, DEFAULT_ROW_ALIGNMENT, Spec.DEFAULT_FLEXIBILITY),
- new Spec(DEFAULT_SPAN, DEFAULT_COLUMN_ALIGNMENT, Spec.DEFAULT_FLEXIBILITY));
+ this(spec(UNDEFINED), spec(UNDEFINED));
}
// Copying constructors
@@ -1753,18 +1765,12 @@
*/
public LayoutParams(LayoutParams that) {
super(that);
- this.columnSpec = new Spec(that.columnSpec);
this.rowSpec = new Spec(that.rowSpec);
+ this.columnSpec = new Spec(that.columnSpec);
}
// AttributeSet constructors
- private LayoutParams(Context context, AttributeSet attrs, int defaultGravity) {
- super(context, attrs);
- reInitSuper(context, attrs);
- init(context, attrs, defaultGravity);
- }
-
/**
* {@inheritDoc}
*
@@ -1772,27 +1778,13 @@
* defined in {@link LayoutParams}.
*/
public LayoutParams(Context context, AttributeSet attrs) {
- this(context, attrs, Gravity.NO_GRAVITY);
+ super(context, attrs);
+ reInitSuper(context, attrs);
+ init(context, attrs);
}
// Implementation
- private static boolean definesVertical(int gravity) {
- return gravity > 0 && (gravity & Gravity.VERTICAL_GRAVITY_MASK) != 0;
- }
-
- private static boolean definesHorizontal(int gravity) {
- return gravity > 0 && (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) != 0;
- }
-
- private static <T> T getAlignment(T[] alignments, T fill, int min, int max,
- boolean isUndefined, T defaultValue) {
- if (isUndefined) {
- return defaultValue;
- }
- return min != max ? fill : alignments[min];
- }
-
// Reinitialise the margins using a different default policy than MarginLayoutParams.
// Here we use the value UNDEFINED (as distinct from zero) to represent the undefined state
// so that a layout manager default can be accessed post set up. We need this as, at the
@@ -1817,44 +1809,20 @@
}
}
- // Gravity. For conversion from the static the integers defined in the Gravity class,
- // use Gravity.apply() to apply gravity to a view of zero size and see where it ends up.
- private static Alignment getColAlignment(int gravity, int width) {
- Rect r = new Rect(0, 0, 0, 0);
- Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r);
-
- boolean fill = (width == MATCH_PARENT);
- Alignment defaultAlignment = fill ? FILL : DEFAULT_COLUMN_ALIGNMENT;
- return getAlignment(COLUMN_ALIGNMENTS, FILL, r.left, r.right,
- !definesHorizontal(gravity), defaultAlignment);
- }
-
- private static Alignment getRowAlignment(int gravity, int height) {
- Rect r = new Rect(0, 0, 0, 0);
- Gravity.apply(gravity, 0, 0, CONTAINER_BOUNDS, r);
-
- boolean fill = (height == MATCH_PARENT);
- Alignment defaultAlignment = fill ? FILL : DEFAULT_ROW_ALIGNMENT;
- return getAlignment(ROW_ALIGNMENTS, FILL, r.top, r.bottom,
- !definesVertical(gravity), defaultAlignment);
- }
-
- private void init(Context context, AttributeSet attrs, int defaultGravity) {
+ private void init(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GridLayout_Layout);
try {
- int gravity = a.getInt(GRAVITY, defaultGravity);
+ int gravity = a.getInt(GRAVITY, Gravity.NO_GRAVITY);
int column = a.getInt(COLUMN, DEFAULT_COLUMN);
- int columnSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
- Interval hSpan = new Interval(column, column + columnSpan);
- int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Spec.DEFAULT_FLEXIBILITY);
- this.columnSpec = new Spec(hSpan, getColAlignment(gravity, width), hFlexibility);
+ int colSpan = a.getInt(COLUMN_SPAN, DEFAULT_SPAN_SIZE);
+ int hFlexibility = a.getInt(COLUMN_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY);
+ this.columnSpec = spec(column, colSpan, getAlignment(gravity, true), hFlexibility);
int row = a.getInt(ROW, DEFAULT_ROW);
int rowSpan = a.getInt(ROW_SPAN, DEFAULT_SPAN_SIZE);
- Interval vSpan = new Interval(row, row + rowSpan);
- int vFlexibility = a.getInt(ROW_FLEXIBILITY, Spec.DEFAULT_FLEXIBILITY);
- this.rowSpec = new Spec(vSpan, getRowAlignment(gravity, height), vFlexibility);
+ int vFlexibility = a.getInt(ROW_FLEXIBILITY, Spec.UNDEFINED_FLEXIBILITY);
+ this.rowSpec = spec(row, rowSpan, getAlignment(gravity, false), vFlexibility);
} finally {
a.recycle();
}
@@ -1869,8 +1837,8 @@
* @attr ref android.R.styleable#GridLayout_Layout_layout_gravity
*/
public void setGravity(int gravity) {
- columnSpec = columnSpec.copyWriteAlignment(getColAlignment(gravity, width));
- rowSpec = rowSpec.copyWriteAlignment(getRowAlignment(gravity, height));
+ rowSpec = rowSpec.copyWriteAlignment(getAlignment(gravity, false));
+ columnSpec = columnSpec.copyWriteAlignment(getAlignment(gravity, true));
}
@Override
@@ -2045,7 +2013,7 @@
public int before;
public int after;
- public int flexibility;
+ public int flexibility; // we're flexible iff all included specs are flexible
private Bounds() {
reset();
@@ -2054,7 +2022,7 @@
protected void reset() {
before = Integer.MIN_VALUE;
after = Integer.MIN_VALUE;
- flexibility = UNDEFINED_FLEXIBILITY;
+ flexibility = CAN_STRETCH; // from the above, we're flexible when empty
}
protected void include(int before, int after) {
@@ -2064,10 +2032,7 @@
protected int size(boolean min) {
if (!min) {
- // Note in the usual case, components don't define anything
- // leaving their flexibility is undefined and their stretchability
- // defined as if the CAN_STRETCH flag was false.
- if (canStretch(flexibility) && !isUndefined(flexibility)) {
+ if (canStretch(flexibility)) {
return MAX_SIZE;
}
}
@@ -2078,11 +2043,12 @@
return before - alignment.getAlignmentValue(c, size);
}
- protected void include(View c, Spec spec, GridLayout gridLayout, Axis axis) {
- this.flexibility &= spec.flexibility;
+ protected final void include(View c, Spec spec, GridLayout gridLayout, Axis axis) {
+ this.flexibility &= spec.getFlexibility();
int size = gridLayout.getMeasurementIncludingMargin(c, axis.horizontal);
// todo test this works correctly when the returned value is UNDEFINED
- int before = spec.alignment.getAlignmentValue(c, size);
+ Alignment alignment = gridLayout.getAlignment(spec.alignment, axis.horizontal);
+ int before = alignment.getAlignmentValue(c, size);
include(before, size - before);
}
@@ -2107,8 +2073,6 @@
* {@code x} such that {@code min <= x < max}.
*/
static class Interval {
- private static final Interval GONE = new Interval(UNDEFINED, UNDEFINED);
-
/**
* The minimum value.
*/
@@ -2186,40 +2150,38 @@
}
}
- /**
- * A spec defines either the horizontal or vertical characteristics of a group of
- * cells.
- */
+ /**
+ * A Spec defines the horizontal or vertical characteristics of a group of
+ * cells. Each spec. defines the <em>grid indices</em>, <em>alignment</em> and
+ * <em>flexibility</em> along the appropriate axis.
+ * <p>
+ * The <em>grid indices</em> are the leading and trailing edges of this cell group.
+ * See {@link GridLayout} for a description of the conventions used by GridLayout
+ * for grid indices.
+ * <p>
+ * The <em>alignment</em> property specifies how cells should be aligned in this group.
+ * For row groups, this specifies the vertical alignment.
+ * For column groups, this specifies the horizontal alignment.
+ */
public static class Spec {
- private static final int DEFAULT_FLEXIBILITY = UNDEFINED_FLEXIBILITY;
+ private static final int UNDEFINED_FLEXIBILITY = UNDEFINED;
- private static final Spec GONE = new Spec(Interval.GONE, Alignment.GONE);
-
- /**
- * The grid indices of the leading and trailing edges of this cell group for the
- * appropriate axis.
- * <p>
- * See {@link GridLayout} for a description of the conventions used by GridLayout
- * for grid indices.
- */
final Interval span;
- /**
- * Specifies how cells should be aligned in this group.
- * For row groups, this specifies the vertical alignment.
- * For column groups, this specifies the horizontal alignment.
- */
+
final Alignment alignment;
- /**
- * The flexibility field tells GridLayout how to derive minimum and maximum size
- * values for a component. Specifications are made with respect to a child's
- * 'measured size'. A child's measured size is, in turn, controlled by its
- * height and width layout parameters which either specify a size or, in
- * the case of {@link LayoutParams#WRAP_CONTENT WRAP_CONTENT}, defer to
- * the computed size of the component.
- *
- * @see GridLayout#CAN_STRETCH
- */
+ /**
+ * The <em>flexibility</em> property tells GridLayout how to derive minimum and maximum size
+ * values for a component. Specifications are made with respect to a child's
+ * 'measured size'. A child's measured size is, in turn, controlled by its
+ * height and width layout parameters which either specify a size or, in
+ * the case of {@link LayoutParams#WRAP_CONTENT WRAP_CONTENT}, defer to
+ * the computed size of the component.
+ * <p>
+ * A cell group is flexible only if <em>all</em> of its components are flexible.
+ * <p>
+ * By default, flexibility is {@link #INFLEXIBLE} only when alignment/gravity is undefined.
+ */
final int flexibility;
private Spec(Interval span, Alignment alignment, int flexibility) {
@@ -2229,7 +2191,7 @@
}
private Spec(Interval span, Alignment alignment) {
- this(span, alignment, DEFAULT_FLEXIBILITY);
+ this(span, alignment, UNDEFINED_FLEXIBILITY);
}
/* Copying constructor */
@@ -2249,8 +2211,14 @@
return new Spec(span, alignment, flexibility);
}
- private Spec copyWriteFlexibility(int flexibility) {
- return new Spec(span, alignment, flexibility);
+ private static int defaultFlexibility(Alignment alignment) {
+ return (alignment == UNDEFINED_ALIGNMENT) ? INFLEXIBLE : CAN_STRETCH;
+ }
+
+ int getFlexibility() {
+ return (flexibility != UNDEFINED_FLEXIBILITY) ?
+ flexibility :
+ defaultFlexibility(alignment);
}
/**
@@ -2293,34 +2261,23 @@
}
/**
- * Return a Spec, {@code spec}, where:
- * <ul>
- * <li> {@code spec.span = [start, start + size]} </li>
- * <li> {@code spec.alignment = alignment} </li>
- * <li> {@code spec.flexibility = flexibility} </li>
- * </ul>
+ * @deprecated Please use {@link #spec(int, int, Alignment)} instead,
+ * all spec's that define alignments (gravity) are assumed to be able to stretch.
*
- * @param start the start
- * @param size the size
- * @param alignment the alignment
- * @param flexibility the flexibility
+ * @hide
*/
+ @Deprecated
public static Spec spec(int start, int size, Alignment alignment, int flexibility) {
return new Spec(start, size, alignment, flexibility);
}
/**
- * Return a Spec, {@code spec}, where:
- * <ul>
- * <li> {@code spec.span = [start, start + 1]} </li>
- * <li> {@code spec.alignment = alignment} </li>
- * <li> {@code spec.flexibility = flexibility} </li>
- * </ul>
+ * @deprecated Please use {@link #spec(int, Alignment)} instead,
+ * all spec's that define alignments (gravity) are assumed to be able to stretch.
*
- * @param start the start
- * @param alignment the alignment
- * @param flexibility the flexibility
+ * @hide
*/
+ @Deprecated
public static Spec spec(int start, Alignment alignment, int flexibility) {
return spec(start, 1, alignment, flexibility);
}
@@ -2337,7 +2294,7 @@
* @param alignment the alignment
*/
public static Spec spec(int start, int size, Alignment alignment) {
- return spec(start, size, alignment, Spec.DEFAULT_FLEXIBILITY);
+ return spec(start, size, alignment, Spec.UNDEFINED_FLEXIBILITY);
}
/**
@@ -2355,6 +2312,31 @@
}
/**
+ * Return a Spec, {@code spec}, where:
+ * <ul>
+ * <li> {@code spec.span = [start, start + size]} </li>
+ * </ul>
+ *
+ * @param start the start
+ * @param size the size
+ */
+ public static Spec spec(int start, int size) {
+ return spec(start, size, UNDEFINED_ALIGNMENT);
+ }
+
+ /**
+ * Return a Spec, {@code spec}, where:
+ * <ul>
+ * <li> {@code spec.span = [start, start + 1]} </li>
+ * </ul>
+ *
+ * @param start the start index
+ */
+ public static Spec spec(int start) {
+ return spec(start, 1);
+ }
+
+ /**
* Alignments specify where a view should be placed within a cell group and
* what size it should be.
* <p>
@@ -2376,13 +2358,6 @@
* <p>
*/
public static abstract class Alignment {
- private static final Alignment GONE = new Alignment() {
- public int getAlignmentValue(View view, int viewSize) {
- assert false;
- return 0;
- }
- };
-
Alignment() {
}
@@ -2422,11 +2397,16 @@
}
}
+ private static final Alignment UNDEFINED_ALIGNMENT = new Alignment() {
+ public int getAlignmentValue(View view, int viewSize) {
+ return UNDEFINED;
+ }
+ };
+
private static final Alignment LEADING = new Alignment() {
public int getAlignmentValue(View view, int viewSize) {
return 0;
}
-
};
private static final Alignment TRAILING = new Alignment() {
@@ -2542,38 +2522,17 @@
return (flexibility & CAN_STRETCH) != 0;
}
- private static boolean isUndefined(int flexibility) {
- return (flexibility & UNDEFINED) != 0;
- }
-
- /**
- * Indicates that a view requests precisely the size specified by its layout parameters.
- *
- * @see Spec#flexibility
- */
- private static final int NONE = 0;
-
- /**
- * Indicates that a view's size should lie between its minimum and the size specified by
- * its layout parameters.
- *
- * @see Spec#flexibility
- */
- private static final int CAN_SHRINK = 1;
+ private static final int INFLEXIBLE = 0;
/**
* Indicates that a view's size should be greater than or equal to the size specified by
* its layout parameters.
*
- * @see Spec#flexibility
- */
- public static final int CAN_STRETCH = 2;
-
- /**
- * A default value for flexibility.
+ * @deprecated Please use {@link #spec(int, int, Alignment)} instead,
+ * all spec's that define alignment (gravity) are assumed to able to stretch.
*
- * @see Spec#flexibility
+ * @hide
*/
- private static final int UNDEFINED_FLEXIBILITY = UNDEFINED | CAN_SHRINK | CAN_STRETCH;
-
+ @Deprecated
+ public static final int CAN_STRETCH = 2;
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 563fc26..36927ca 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -91,6 +91,7 @@
private boolean mLayoutInScreen;
private boolean mClipToScreen;
private boolean mAllowScrollingAnchorParent = true;
+ private boolean mLayoutInsetDecor = false;
private OnTouchListener mTouchInterceptor;
@@ -658,6 +659,22 @@
}
/**
+ * Allows the popup window to force the flag
+ * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
+ * This will cause the popup to inset its content to account for system windows overlaying
+ * the screen, such as the status bar.
+ *
+ * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
+ *
+ * @param enabled true if the popup's views should inset content to account for system windows,
+ * the way that decor views behave for full-screen windows.
+ * @hide
+ */
+ public void setLayoutInsetDecor(boolean enabled) {
+ mLayoutInsetDecor = enabled;
+ }
+
+ /**
* Set the layout type for this window. Should be one of the TYPE constants defined in
* {@link WindowManager.LayoutParams}.
*
@@ -942,6 +959,7 @@
if (mContext != null) {
p.packageName = mContext.getPackageName();
}
+ mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
mWindowManager.addView(mPopupView, p);
}
@@ -1012,6 +1030,9 @@
if (mLayoutInScreen) {
curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
}
+ if (mLayoutInsetDecor) {
+ curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+ }
return curFlags;
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 867ebb4..7b43032 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -92,6 +92,12 @@
public boolean onRemoteAdapterConnected();
public void onRemoteAdapterDisconnected();
+
+ /**
+ * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
+ * connected yet.
+ */
+ public void deferNotifyDataSetChanged();
}
/**
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index b2d1a1e..8b4d3a9 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -45,6 +45,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
+import android.view.CollapsibleActionView;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -58,18 +59,30 @@
import java.util.WeakHashMap;
/**
- * A widget that provides a user interface for the user to enter a search query and submit a
- * request to a search provider. Shows a list of query suggestions or results, if
- * available, and allows the user to pick a suggestion or result to launch into.
+ * A widget that provides a user interface for the user to enter a search query and submit a request
+ * to a search provider. Shows a list of query suggestions or results, if available, and allows the
+ * user to pick a suggestion or result to launch into.
*
- * <p>For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
- * documentation.<p>
+ * <p>
+ * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it
+ * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean)
+ * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done.
+ * </p>
+ * <p>
+ * If you want the search field to always be visible, then call setIconifiedByDefault(false).
+ * </p>
*
+ * <p>
+ * For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
+ * documentation.
+ * <p>
+ *
+ * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
* @attr ref android.R.styleable#SearchView_iconifiedByDefault
* @attr ref android.R.styleable#SearchView_maxWidth
* @attr ref android.R.styleable#SearchView_queryHint
*/
-public class SearchView extends LinearLayout {
+public class SearchView extends LinearLayout implements CollapsibleActionView {
private static final boolean DBG = false;
private static final String LOG_TAG = "SearchView";
@@ -100,10 +113,26 @@
private int mMaxWidth;
private boolean mVoiceButtonEnabled;
private CharSequence mUserQuery;
+ private boolean mExpandedInActionView;
private SearchableInfo mSearchable;
private Bundle mAppSearchData;
+ /*
+ * SearchView can be set expanded before the IME is ready to be shown during
+ * initial UI setup. The show operation is asynchronous to account for this.
+ */
+ private Runnable mShowImeRunnable = new Runnable() {
+ public void run() {
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ if (imm != null) {
+ imm.showSoftInputUnchecked(0, null);
+ }
+ }
+ };
+
// For voice searching
private final Intent mVoiceWebSearchIntent;
private final Intent mVoiceAppSearchIntent;
@@ -207,6 +236,7 @@
mCloseButton.setOnClickListener(mOnClickListener);
mSubmitButton.setOnClickListener(mOnClickListener);
mVoiceButton.setOnClickListener(mOnClickListener);
+ mQueryTextView.setOnClickListener(mOnClickListener);
mQueryTextView.addTextChangedListener(mTextWatcher);
mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
@@ -305,7 +335,9 @@
// If it is not iconified, then give the focus to the text field
if (!isIconified()) {
boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
- if (result) updateViewsVisibility(false);
+ if (result) {
+ updateViewsVisibility(false);
+ }
return result;
} else {
return super.requestFocus(direction, previouslyFocusedRect);
@@ -316,9 +348,9 @@
@Override
public void clearFocus() {
mClearingFocus = true;
+ setImeVisibility(false);
super.clearFocus();
mQueryTextView.clearFocus();
- setImeVisibility(false);
mClearingFocus = false;
}
@@ -623,7 +655,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;
+ final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
}
@@ -633,16 +665,15 @@
mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
}
- private void setImeVisibility(boolean visible) {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ private void setImeVisibility(final boolean visible) {
+ if (visible) {
+ post(mShowImeRunnable);
+ } else {
+ removeCallbacks(mShowImeRunnable);
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- // We made sure the IME was displayed, so also make sure it is closed
- // when we go away.
- if (imm != null) {
- if (visible) {
- imm.showSoftInputUnchecked(0, null);
- } else {
+ if (imm != null) {
imm.hideSoftInputFromWindow(getWindowToken(), 0);
}
}
@@ -667,6 +698,8 @@
onSubmitQuery();
} else if (v == mVoiceButton) {
onVoiceClicked();
+ } else if (v == mQueryTextView) {
+ forceSuggestionQuery();
}
}
};
@@ -1015,6 +1048,9 @@
void onTextFocusChanged() {
updateViewsVisibility(isIconified());
updateFocusedState(mQueryTextView.hasFocus());
+ if (mQueryTextView.hasFocus()) {
+ forceSuggestionQuery();
+ }
}
@Override
@@ -1022,6 +1058,26 @@
super.onAttachedToWindow();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActionViewCollapsed() {
+ clearFocus();
+ updateViewsVisibility(true);
+ mQueryTextView.setText("");
+ mExpandedInActionView = false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActionViewExpanded() {
+ mExpandedInActionView = true;
+ setIconified(false);
+ }
+
private void adjustDropDownSizeAndPosition() {
if (mDropDownAnchor.getWidth() > 1) {
Resources res = getContext().getResources();
@@ -1343,6 +1399,11 @@
}
}
+ private void forceSuggestionQuery() {
+ mQueryTextView.doBeforeTextChanged();
+ mQueryTextView.doAfterTextChanged();
+ }
+
static boolean isLandscapeMode(Context context) {
return context.getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index b7565f3..0c80a11 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -34,6 +34,7 @@
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
@@ -360,6 +361,13 @@
}
}
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
+ event.getText().add(switchText.getText());
+ }
+
private Layout makeLayout(CharSequence text) {
return new StaticLayout(text, mTextPaint,
(int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)),
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a7324b0..127b6a3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -329,7 +329,6 @@
private int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout;
private int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout;
- private int mTextEditSuggestionsWindowLayout;
private int mTextEditSuggestionItemLayout;
private SuggestionsPopupWindow mSuggestionsPopupWindow;
private SuggestionRangeSpan mSuggestionRangeSpan;
@@ -830,10 +829,6 @@
mTextEditSideNoPasteWindowLayout = a.getResourceId(attr, 0);
break;
- case com.android.internal.R.styleable.TextView_textEditSuggestionsWindowLayout:
- mTextEditSuggestionsWindowLayout = a.getResourceId(attr, 0);
- break;
-
case com.android.internal.R.styleable.TextView_textEditSuggestionItemLayout:
mTextEditSuggestionItemLayout = a.getResourceId(attr, 0);
break;
@@ -8780,20 +8775,48 @@
private class SuggestionsPopupWindow implements OnClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = 5;
private static final int NO_SUGGESTIONS = -1;
- private final PopupWindow mContainer;
- private ViewGroup mSuggestionViewGroup;
+ private final PopupWindow mPopupWindow;
+ private LinearLayout mSuggestionsContainer;
private WordIterator mSuggestionWordIterator;
private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
public SuggestionsPopupWindow() {
- mContainer = new PopupWindow(TextView.this.mContext, null,
+ mPopupWindow = new PopupWindow(TextView.this.mContext, null,
com.android.internal.R.attr.textSuggestionsWindowStyle);
- mContainer.setSplitTouchEnabled(true);
- mContainer.setClippingEnabled(false);
- mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+ mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+ mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+ mPopupWindow.setOutsideTouchable(true);
- mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
- mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+ mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+ mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ mSuggestionsContainer = new LinearLayout(TextView.this.mContext);
+ mSuggestionsContainer.setOrientation(LinearLayout.VERTICAL);
+
+ LayoutInflater inflater = (LayoutInflater) TextView.this.mContext.
+ getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ if (inflater == null) {
+ throw new IllegalArgumentException(
+ "Unable to create inflater for TextEdit suggestions");
+ }
+
+ // Inflate the suggestion items once and for all.
+ for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
+ View childView = inflater.inflate(mTextEditSuggestionItemLayout,
+ mSuggestionsContainer, false);
+
+ if (! (childView instanceof TextView)) {
+ throw new IllegalArgumentException(
+ "Inflated TextEdit suggestion item is not a TextView: " + childView);
+ }
+
+ childView.setTag(new SuggestionInfo());
+ mSuggestionsContainer.addView(childView);
+ childView.setOnClickListener(this);
+ }
+
+ mPopupWindow.setContentView(mSuggestionsContainer);
}
private class SuggestionInfo {
@@ -8803,44 +8826,6 @@
int suggestionIndex; // the index of the suggestion inside suggestionSpan
}
- private void initSuggestionViewGroup() {
- if (mSuggestionViewGroup == null) {
- LayoutInflater inflater = (LayoutInflater) TextView.this.mContext.
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- if (inflater == null) {
- throw new IllegalArgumentException(
- "Unable to create TextEdit suggestion window inflater");
- }
-
- View view = inflater.inflate(mTextEditSuggestionsWindowLayout, null);
-
- if (! (view instanceof ViewGroup)) {
- throw new IllegalArgumentException(
- "Inflated TextEdit suggestion window is not a ViewGroup: " + view);
- }
-
- mSuggestionViewGroup = (ViewGroup) view;
-
- // Inflate the suggestion items once and for all.
- for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
- View childView = inflater.inflate(mTextEditSuggestionItemLayout,
- mSuggestionViewGroup, false);
-
- if (! (childView instanceof TextView)) {
- throw new IllegalArgumentException(
- "Inflated TextEdit suggestion item is not a TextView: " + childView);
- }
-
- childView.setTag(new SuggestionInfo());
- mSuggestionViewGroup.addView(childView);
- childView.setOnClickListener(this);
- }
-
- mContainer.setContentView(mSuggestionViewGroup);
- }
- }
-
public void show() {
if (!(mText instanceof Editable)) return;
@@ -8849,8 +8834,6 @@
SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
final int nbSpans = suggestionSpans.length;
- initSuggestionViewGroup();
-
int totalNbSuggestions = 0;
int spanUnionStart = mText.length();
int spanUnionEnd = 0;
@@ -8865,7 +8848,7 @@
String[] suggestions = suggestionSpan.getSuggestions();
int nbSuggestions = suggestions.length;
for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
- TextView textView = (TextView) mSuggestionViewGroup.getChildAt(
+ TextView textView = (TextView) mSuggestionsContainer.getChildAt(
totalNbSuggestions);
textView.setText(suggestions[suggestionIndex]);
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
@@ -8885,7 +8868,7 @@
if (totalNbSuggestions == 0) {
// TODO Replace by final text, use a dedicated layout, add a fade out timer...
- TextView textView = (TextView) mSuggestionViewGroup.getChildAt(0);
+ TextView textView = (TextView) mSuggestionsContainer.getChildAt(0);
textView.setText("No suggestions available");
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
suggestionInfo.spanStart = NO_SUGGESTIONS;
@@ -8896,22 +8879,22 @@
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
for (int i = 0; i < totalNbSuggestions; i++) {
- final TextView textView = (TextView) mSuggestionViewGroup.getChildAt(i);
+ final TextView textView = (TextView) mSuggestionsContainer.getChildAt(i);
highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
}
}
for (int i = 0; i < totalNbSuggestions; i++) {
- mSuggestionViewGroup.getChildAt(i).setVisibility(VISIBLE);
+ mSuggestionsContainer.getChildAt(i).setVisibility(VISIBLE);
}
for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
- mSuggestionViewGroup.getChildAt(i).setVisibility(GONE);
+ mSuggestionsContainer.getChildAt(i).setVisibility(GONE);
}
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
final int screenWidth = displayMetrics.widthPixels;
final int screenHeight = displayMetrics.heightPixels;
- mSuggestionViewGroup.measure(
+ mSuggestionsContainer.measure(
View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.AT_MOST));
@@ -9071,11 +9054,11 @@
if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
((Editable) mText).removeSpan(mSuggestionRangeSpan);
}
- mContainer.dismiss();
+ mPopupWindow.dismiss();
}
public boolean isShowing() {
- return mContainer.isShowing();
+ return mPopupWindow.isShowing();
}
@Override
@@ -9139,7 +9122,7 @@
}
void positionAtCursor() {
- View contentView = mContainer.getContentView();
+ View contentView = mPopupWindow.getContentView();
int width = contentView.getMeasuredWidth();
int height = contentView.getMeasuredHeight();
final int offset = TextView.this.getSelectionStart();
@@ -9173,7 +9156,7 @@
coords[0] = Math.min(displayMetrics.widthPixels - width, coords[0]);
coords[0] = Math.max(0, coords[0]);
- mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
+ mPopupWindow.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
}
}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 95f1f98..bc87153 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -35,10 +35,13 @@
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
+import android.util.TypedValue;
import android.view.ActionMode;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -61,6 +64,7 @@
private static final String TAG = "ActionBarImpl";
private Context mContext;
+ private Context mThemedContext;
private Activity mActivity;
private Dialog mDialog;
@@ -188,8 +192,7 @@
mContentHeight = mActionView.getContentHeight();
if (mTabScrollView != null) {
- mTabScrollView.getLayoutParams().height = mContentHeight;
- mTabScrollView.requestLayout();
+ mTabScrollView.setContentHeight(mContentHeight);
}
}
@@ -605,6 +608,23 @@
}
}
+ public Context getThemedContext() {
+ if (mThemedContext == null) {
+ TypedValue outValue = new TypedValue();
+ Resources.Theme currentTheme = mContext.getTheme();
+ currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
+ outValue, true);
+ final int targetThemeRes = outValue.resourceId;
+
+ if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
+ mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
+ } else {
+ mThemedContext = mContext;
+ }
+ }
+ return mThemedContext;
+ }
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 9ae7def..1531946 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -1,22 +1,9 @@
package com.android.internal.content;
-import android.content.pm.PackageManager;
import android.os.Build;
-import android.os.FileUtils;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.util.Pair;
import android.util.Slog;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
/**
* Native libraries helper.
@@ -28,270 +15,22 @@
private static final boolean DEBUG_NATIVE = false;
- /*
- * The following constants are returned by listPackageSharedLibsForAbiLI
- * to indicate if native shared libraries were found in the package.
- * Values are:
- * PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES => native libraries found and installed
- * PACKAGE_INSTALL_NATIVE_NO_LIBRARIES => no native libraries in package
- * PACKAGE_INSTALL_NATIVE_ABI_MISMATCH => native libraries for another ABI found
- * in package (and not installed)
- *
- */
- private static final int PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES = 0;
- private static final int PACKAGE_INSTALL_NATIVE_NO_LIBRARIES = 1;
- private static final int PACKAGE_INSTALL_NATIVE_ABI_MISMATCH = 2;
+ private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);
- // Directory in the APK that holds all the native shared libraries.
- private static final String APK_LIB = "lib/";
- private static final int APK_LIB_LENGTH = APK_LIB.length();
-
- // Prefix that native shared libraries must have.
- private static final String LIB_PREFIX = "lib";
- private static final int LIB_PREFIX_LENGTH = LIB_PREFIX.length();
-
- // Suffix that the native shared libraries must have.
- private static final String LIB_SUFFIX = ".so";
- private static final int LIB_SUFFIX_LENGTH = LIB_SUFFIX.length();
-
- // Name of the GDB binary.
- private static final String GDBSERVER = "gdbserver";
-
- // the minimum length of a valid native shared library of the form
- // lib/<something>/lib<name>.so.
- private static final int MIN_ENTRY_LENGTH = APK_LIB_LENGTH + 2 + LIB_PREFIX_LENGTH + 1
- + LIB_SUFFIX_LENGTH;
-
- /*
- * Find all files of the form lib/<cpuAbi>/lib<name>.so in the .apk
- * and add them to a list to be installed later.
- *
- * NOTE: this method may throw an IOException if the library cannot
- * be copied to its final destination, e.g. if there isn't enough
- * room left on the data partition, or a ZipException if the package
- * file is malformed.
- */
- private static int listPackageSharedLibsForAbiLI(ZipFile zipFile,
- String cpuAbi, List<Pair<ZipEntry, String>> libEntries) throws IOException,
- ZipException {
- final int cpuAbiLen = cpuAbi.length();
- boolean hasNativeLibraries = false;
- boolean installedNativeLibraries = false;
-
- if (DEBUG_NATIVE) {
- Slog.d(TAG, "Checking " + zipFile.getName() + " for shared libraries of CPU ABI type "
- + cpuAbi);
- }
-
- Enumeration<? extends ZipEntry> entries = zipFile.entries();
-
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
-
- // skip directories
- if (entry.isDirectory()) {
- continue;
- }
- String entryName = entry.getName();
-
- /*
- * Check that the entry looks like lib/<something>/lib<name>.so
- * here, but don't check the ABI just yet.
- *
- * - must be sufficiently long
- * - must end with LIB_SUFFIX, i.e. ".so"
- * - must start with APK_LIB, i.e. "lib/"
- */
- if (entryName.length() < MIN_ENTRY_LENGTH || !entryName.endsWith(LIB_SUFFIX)
- || !entryName.startsWith(APK_LIB)) {
- continue;
- }
-
- // file name must start with LIB_PREFIX, i.e. "lib"
- int lastSlash = entryName.lastIndexOf('/');
-
- if (lastSlash < 0
- || !entryName.regionMatches(lastSlash + 1, LIB_PREFIX, 0, LIB_PREFIX_LENGTH)) {
- continue;
- }
-
- hasNativeLibraries = true;
-
- // check the cpuAbi now, between lib/ and /lib<name>.so
- if (lastSlash != APK_LIB_LENGTH + cpuAbiLen
- || !entryName.regionMatches(APK_LIB_LENGTH, cpuAbi, 0, cpuAbiLen))
- continue;
-
- /*
- * Extract the library file name, ensure it doesn't contain
- * weird characters. we're guaranteed here that it doesn't contain
- * a directory separator though.
- */
- String libFileName = entryName.substring(lastSlash+1);
- if (!FileUtils.isFilenameSafe(new File(libFileName))) {
- continue;
- }
-
- installedNativeLibraries = true;
-
- if (DEBUG_NATIVE) {
- Log.d(TAG, "Caching shared lib " + entry.getName());
- }
-
- libEntries.add(Pair.create(entry, libFileName));
- }
- if (!hasNativeLibraries)
- return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
-
- if (!installedNativeLibraries)
- return PACKAGE_INSTALL_NATIVE_ABI_MISMATCH;
-
- return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
+ public static long sumNativeBinariesLI(File apkFile) {
+ final String cpuAbi = Build.CPU_ABI;
+ final String cpuAbi2 = Build.CPU_ABI2;
+ return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2);
}
- /*
- * Find the gdbserver executable program in a package at
- * lib/<cpuAbi>/gdbserver and add it to the list of binaries
- * to be copied out later.
- *
- * Returns PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES on success,
- * or PACKAGE_INSTALL_NATIVE_NO_LIBRARIES otherwise.
- */
- private static int listPackageGdbServerLI(ZipFile zipFile, String cpuAbi,
- List<Pair<ZipEntry, String>> nativeFiles) throws IOException, ZipException {
- final String apkGdbServerPath = "lib/" + cpuAbi + "/" + GDBSERVER;
+ private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
+ String cpuAbi, String cpuAbi2);
- Enumeration<? extends ZipEntry> entries = zipFile.entries();
-
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
- // skip directories
- if (entry.isDirectory()) {
- continue;
- }
- String entryName = entry.getName();
-
- if (!entryName.equals(apkGdbServerPath)) {
- continue;
- }
-
- if (false) {
- Log.d(TAG, "Found gdbserver: " + entry.getName());
- }
-
- final String installGdbServerPath = GDBSERVER;
- nativeFiles.add(Pair.create(entry, installGdbServerPath));
-
- return PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES;
- }
- return PACKAGE_INSTALL_NATIVE_NO_LIBRARIES;
- }
-
- /*
- * Examine shared libraries stored in the APK as
- * lib/<cpuAbi>/lib<name>.so and add them to a list to be copied
- * later.
- *
- * This function will first try the main CPU ABI defined by Build.CPU_ABI
- * (which corresponds to ro.product.cpu.abi), and also try an alternate
- * one if ro.product.cpu.abi2 is defined.
- */
- public static int listPackageNativeBinariesLI(ZipFile zipFile,
- List<Pair<ZipEntry, String>> nativeFiles) throws ZipException, IOException {
- String cpuAbi = Build.CPU_ABI;
-
- int result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi, nativeFiles);
-
- /*
- * Some architectures are capable of supporting several CPU ABIs
- * for example, 'armeabi-v7a' also supports 'armeabi' native code
- * this is indicated by the definition of the ro.product.cpu.abi2
- * system property.
- *
- * only scan the package twice in case of ABI mismatch
- */
- if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
- final String cpuAbi2 = SystemProperties.get("ro.product.cpu.abi2", null);
- if (cpuAbi2 != null) {
- result = listPackageSharedLibsForAbiLI(zipFile, cpuAbi2, nativeFiles);
- }
-
- if (result == PACKAGE_INSTALL_NATIVE_ABI_MISMATCH) {
- Slog.w(TAG, "Native ABI mismatch from package file");
- return PackageManager.INSTALL_FAILED_INVALID_APK;
- }
-
- if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
- cpuAbi = cpuAbi2;
- }
- }
-
- /*
- * Debuggable packages may have gdbserver embedded, so add it to
- * the list to the list of items to be extracted (as lib/gdbserver)
- * into the application's native library directory later.
- */
- if (result == PACKAGE_INSTALL_NATIVE_FOUND_LIBRARIES) {
- listPackageGdbServerLI(zipFile, cpuAbi, nativeFiles);
- }
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- public static int copyNativeBinariesLI(File scanFile, File sharedLibraryDir) {
- /*
- * Check all the native files that need to be copied and add
- * that to the container size.
- */
- ZipFile zipFile;
- try {
- zipFile = new ZipFile(scanFile);
-
- List<Pair<ZipEntry, String>> nativeFiles = new LinkedList<Pair<ZipEntry, String>>();
-
- NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
-
- final int N = nativeFiles.size();
-
- for (int i = 0; i < N; i++) {
- final Pair<ZipEntry, String> entry = nativeFiles.get(i);
-
- File destFile = new File(sharedLibraryDir, entry.second);
- copyNativeBinaryLI(zipFile, entry.first, sharedLibraryDir, destFile);
- }
- zipFile.close();
- } catch (ZipException e) {
- Slog.w(TAG, "Failed to extract data from package file", e);
- return PackageManager.INSTALL_FAILED_INVALID_APK;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to cache package shared libs", e);
- return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- }
-
- return PackageManager.INSTALL_SUCCEEDED;
- }
-
- private static void copyNativeBinaryLI(ZipFile zipFile, ZipEntry entry,
- File binaryDir, File binaryFile) throws IOException {
- InputStream inputStream = zipFile.getInputStream(entry);
- try {
- File tempFile = File.createTempFile("tmp", "tmp", binaryDir);
- String tempFilePath = tempFile.getPath();
- // XXX package manager can't change owner, so the executable files for
- // now need to be left as world readable and owned by the system.
- if (!FileUtils.copyToFile(inputStream, tempFile)
- || !tempFile.setLastModified(entry.getTime())
- || FileUtils.setPermissions(tempFilePath, FileUtils.S_IRUSR | FileUtils.S_IWUSR
- | FileUtils.S_IRGRP | FileUtils.S_IXUSR | FileUtils.S_IXGRP
- | FileUtils.S_IXOTH | FileUtils.S_IROTH, -1, -1) != 0
- || !tempFile.renameTo(binaryFile)) {
- // Failed to properly write file.
- tempFile.delete();
- throw new IOException("Couldn't create cached binary " + binaryFile + " in "
- + binaryDir);
- }
- } finally {
- inputStream.close();
- }
+ public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
+ final String cpuAbi = Build.CPU_ABI;
+ final String cpuAbi2 = Build.CPU_ABI2;
+ return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi,
+ cpuAbi2);
}
// Convenience method to call removeNativeBinariesFromDirLI(File)
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6ec186d..16336e0 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -474,7 +474,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index 2a045e3..eae1ac8 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -32,5 +32,6 @@
in ITextServicesSessionListener tsListener,
in ISpellCheckerSessionListener scListener);
oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
+ oneway void setCurrentSpellChecker(in SpellCheckerInfo info);
SpellCheckerInfo[] getEnabledSpellCheckers();
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index bf2965b..bff621c 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -36,8 +36,8 @@
private boolean mReserveOverflow;
private ActionMenuPresenter mPresenter;
- private boolean mUpdateContentsBeforeMeasure;
private boolean mFormatItems;
+ private int mFormatItemsWidth;
private int mMinCellSize;
private int mMeasuredExtraWidth;
@@ -71,19 +71,21 @@
}
@Override
- public void requestLayout() {
- // Layout can influence how many action items fit.
- mUpdateContentsBeforeMeasure = true;
- super.requestLayout();
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// If we've been given an exact size to match, apply special formatting during layout.
+ final boolean wasFormatted = mFormatItems;
mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
- if (mUpdateContentsBeforeMeasure && mMenu != null) {
+
+ if (wasFormatted != mFormatItems) {
+ mFormatItemsWidth = 0; // Reset this when switching modes
+ }
+
+ // Special formatting can change whether items can fit as action buttons.
+ // Kick the menu and update presenters when this changes.
+ final int widthSize = MeasureSpec.getMode(widthMeasureSpec);
+ if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
+ mFormatItemsWidth = widthSize;
mMenu.onItemsChanged(true);
- mUpdateContentsBeforeMeasure = false;
}
if (mFormatItems) {
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 159b3da..7839a08 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -47,7 +47,7 @@
* standard menu UI.
*/
public class MenuBuilder implements Menu {
- private static final String LOGTAG = "MenuBuilder";
+ private static final String TAG = "MenuBuilder";
private static final String PRESENTER_KEY = "android:menu:presenters";
private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index b0a002d..8b53bb8 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -563,7 +563,7 @@
public MenuItem setActionView(int resId) {
final Context context = mMenu.getContext();
final LayoutInflater inflater = LayoutInflater.from(context);
- setActionView(inflater.inflate(resId, new LinearLayout(context)));
+ setActionView(inflater.inflate(resId, new LinearLayout(context), false));
return this;
}
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 9fef2a9..a2d492b 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -109,6 +109,7 @@
mTabContainer = tabView;
if (tabView != null) {
addView(tabView);
+ tabView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 09262e0..446c842 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -33,6 +33,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -172,7 +173,8 @@
// Background is always provided by the container.
setBackgroundResource(0);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
+ com.android.internal.R.attr.actionBarStyle, 0);
ApplicationInfo appInfo = context.getApplicationInfo();
PackageManager pm = context.getPackageManager();
@@ -250,6 +252,18 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Action bar can change size on configuration changes.
+ // Reread the desired height from the theme-specified style.
+ TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
+ com.android.internal.R.attr.actionBarStyle, 0);
+ setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
+ a.recycle();
+ }
+
+ @Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mTabSelector);
@@ -318,6 +332,7 @@
mIncludeTabs = tabs != null;
if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
addView(mTabScrollView);
+ mTabScrollView.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
}
}
@@ -1323,11 +1338,18 @@
if (mExpandedActionView instanceof CollapsibleActionView) {
((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
}
+
return true;
}
@Override
public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+ // Do this before detaching the actionview from the hierarchy, in case
+ // it needs to dismiss the soft keyboard, etc.
+ if (mExpandedActionView instanceof CollapsibleActionView) {
+ ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
+ }
+
removeView(mExpandedActionView);
removeView(mExpandedHomeLayout);
if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
@@ -1349,16 +1371,12 @@
if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
mCustomNavView.setVisibility(VISIBLE);
}
- View collapsedView = mExpandedActionView;
mExpandedActionView = null;
mExpandedHomeLayout.setIcon(null);
mCurrentExpandedItem = null;
requestLayout();
item.setActionViewExpanded(false);
- if (collapsedView instanceof CollapsibleActionView) {
- ((CollapsibleActionView) collapsedView).onActionViewCollapsed();
- }
return true;
}
diff --git a/core/java/com/android/internal/widget/DialogTitle.java b/core/java/com/android/internal/widget/DialogTitle.java
index cd165dc..b86c438 100644
--- a/core/java/com/android/internal/widget/DialogTitle.java
+++ b/core/java/com/android/internal/widget/DialogTitle.java
@@ -53,21 +53,19 @@
final int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
if (ellipsisCount > 0) {
setSingleLine(false);
-
- TypedArray a = mContext.obtainStyledAttributes(null,
- android.R.styleable.TextAppearance,
- android.R.attr.textAppearanceMedium,
+ setMaxLines(2);
+
+ final TypedArray a = mContext.obtainStyledAttributes(null,
+ android.R.styleable.TextAppearance, android.R.attr.textAppearanceMedium,
android.R.style.TextAppearance_Medium);
final int textSize = a.getDimensionPixelSize(
- android.R.styleable.TextAppearance_textSize,
- (int) (20 * getResources().getDisplayMetrics().density));
- final int textColor = a.getColor(
- android.R.styleable.TextAppearance_textColor, 0xffffffff);
+ android.R.styleable.TextAppearance_textSize, 0);
+ if (textSize != 0) {
+ // textSize is already expressed in pixels
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+ }
+ a.recycle();
- // textSize is already expressed in pixels
- setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
- setTextColor(textColor);
- setMaxLines(2);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index bbddf29..e4322c6 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -892,18 +892,6 @@
}
/**
- * Sets the visibility of emergency call prompt based on emergency capable
- * @param emergencyText the emergency call text to be updated
- */
- public void updateEmergencyCallText(TextView emergencyText) {
- if (isEmergencyCallCapable()) {
- emergencyText.setVisibility(View.VISIBLE);
- } else {
- emergencyText.setVisibility(View.GONE);
- }
- }
-
- /**
* Resumes a call in progress. Typically launched from the EmergencyCall button
* on various lockscreens.
*
@@ -920,4 +908,22 @@
}
return false;
}
+
+ /**
+ * Performs concentenation of PLMN/SPN
+ * @param plmn
+ * @param spn
+ * @return
+ */
+ public static CharSequence getCarrierString(CharSequence plmn, CharSequence spn) {
+ if (plmn != null && spn == null) {
+ return plmn;
+ } else if (plmn != null && spn != null) {
+ return plmn + "|" + spn;
+ } else if (plmn == null && spn != null) {
+ return spn;
+ } else {
+ return "";
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/LockScreenWidgetCallback.java b/core/java/com/android/internal/widget/LockScreenWidgetCallback.java
new file mode 100644
index 0000000..d6403e9f
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockScreenWidgetCallback.java
@@ -0,0 +1,36 @@
+/*
+ * 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.internal.widget;
+
+import android.view.View;
+
+/**
+ * An interface used by LockScreenWidgets to send messages to lock screen.
+ */
+public interface LockScreenWidgetCallback {
+ // Sends a message to lock screen requesting the given view be shown. May be ignored, depending
+ // on lock screen state. View must be the top-level lock screen widget or it will be ignored.
+ public void requestShow(View self);
+
+ // Sends a message to lock screen requesting the view to be hidden.
+ public void requestHide(View self);
+
+ // Sends a message to lock screen that user has interacted with widget. This should be used
+ // exclusively in response to user activity, i.e. user hits a button in the view.
+ public void userActivity(View self);
+
+}
diff --git a/core/java/com/android/internal/widget/LockScreenWidgetInterface.java b/core/java/com/android/internal/widget/LockScreenWidgetInterface.java
new file mode 100644
index 0000000..6dfcc75
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockScreenWidgetInterface.java
@@ -0,0 +1,23 @@
+/*
+ * 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.internal.widget;
+
+public interface LockScreenWidgetInterface {
+
+ public void setCallback(LockScreenWidgetCallback callback);
+
+}
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 40e5e8a..fefa223 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -87,6 +87,11 @@
}
}
+ public void setContentHeight(int contentHeight) {
+ mTabLayout.getLayoutParams().height = contentHeight;
+ requestLayout();
+ }
+
public void animateToVisibility(int visibility) {
if (mVisibilityAnim != null) {
mVisibilityAnim.cancel();
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
new file mode 100644
index 0000000..3961de3
--- /dev/null
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -0,0 +1,103 @@
+/*
+ * 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.internal.widget;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.LinearLayout;
+
+/**
+ * A special widget for displaying audio playback ("transport controls") in LockScreen.
+ *
+ */
+public class TransportControlView extends LinearLayout implements LockScreenWidgetInterface,
+ OnClickListener {
+ private static final String TAG = "TransportControlView";
+ static final int sViewIds[] = { R.id.control_prev, R.id.control_pauseplay, R.id.control_next };
+ protected static final int AUDIO_FOCUS_CHANGED = 100;
+ private LockScreenWidgetCallback mCallback;
+
+ private Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what){
+ case AUDIO_FOCUS_CHANGED:
+ handleAudioFocusChange(msg.arg1);
+ }
+ }
+ };
+
+ AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
+ new AudioManager.OnAudioFocusChangeListener() {
+ public void onAudioFocusChange(final int focusChange) {
+ mHandler.obtainMessage(AUDIO_FOCUS_CHANGED, focusChange, 0).sendToTarget();
+ }
+ };
+
+ public TransportControlView(Context context) {
+ this(context, null);
+ }
+
+ public TransportControlView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ protected void handleAudioFocusChange(int focusChange) {
+ // TODO
+ }
+
+ public void setCallback(LockScreenWidgetCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onFinishInflate() {
+ for (int i = 0; i < sViewIds.length; i++) {
+ View view = findViewById(sViewIds[i]);
+ if (view != null) {
+ view.setOnClickListener(this);
+ }
+ }
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.control_prev:
+ // TODO
+ break;
+
+ case R.id.control_pauseplay:
+ // TODO
+ break;
+
+ case R.id.control_next:
+ // TODO
+ break;
+ }
+ // Have any button click extend lockscreen's timeout.
+ if (mCallback != null) {
+ mCallback.userActivity(this);
+ }
+ }
+
+}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 04bb689..0510023 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -36,6 +36,7 @@
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.MeasureSpec;
import com.android.internal.R;
@@ -45,7 +46,7 @@
*/
public class MultiWaveView extends View {
private static final String TAG = "MultiWaveView";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
// Wave state machine
private static final int STATE_IDLE = 0;
@@ -195,14 +196,41 @@
protected int getSuggestedMinimumWidth() {
// View should be large enough to contain the background + target drawable on either edge
return mOuterRing.getWidth()
- + (mTargetDrawables.size() > 0 ? (mTargetDrawables.get(0).getWidth()) : 0);
+ + (mTargetDrawables.size() > 0 ? (mTargetDrawables.get(0).getWidth()/2) : 0);
}
@Override
protected int getSuggestedMinimumHeight() {
// View should be large enough to contain the unlock ring + target drawable on either edge
return mOuterRing.getHeight()
- + (mTargetDrawables.size() > 0 ? (mTargetDrawables.get(0).getHeight()) : 0);
+ + (mTargetDrawables.size() > 0 ? (mTargetDrawables.get(0).getHeight()/2) : 0);
+ }
+
+ private int resolveMeasured(int measureSpec, int desired)
+ {
+ int result = 0;
+ int specSize = MeasureSpec.getSize(measureSpec);
+ switch (MeasureSpec.getMode(measureSpec)) {
+ case MeasureSpec.UNSPECIFIED:
+ result = desired;
+ break;
+ case MeasureSpec.AT_MOST:
+ result = Math.min(specSize, desired);
+ break;
+ case MeasureSpec.EXACTLY:
+ default:
+ result = specSize;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int minimumWidth = getSuggestedMinimumWidth();
+ final int minimumHeight = getSuggestedMinimumHeight();
+ int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
+ int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
+ setMeasuredDimension(viewWidth, viewHeight);
}
private void switchToState(int state, float x, float y) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 514e59d..6e73889 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -29,6 +29,7 @@
ActivityManager.cpp \
AndroidRuntime.cpp \
Time.cpp \
+ com_android_internal_content_NativeLibraryHelper.cpp \
com_google_android_gles_jni_EGLImpl.cpp \
com_google_android_gles_jni_GLImpl.cpp.arm \
android_app_NativeActivity.cpp \
@@ -178,6 +179,7 @@
external/icu4c/common \
external/jpeg \
external/harfbuzz/src \
+ external/zlib \
frameworks/opt/emoji \
libcore/include
@@ -211,6 +213,7 @@
libnfc_ndef \
libusbhost \
libharfbuzz \
+ libz \
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6ab8fe3..9e46d80 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -175,6 +175,7 @@
extern int register_android_content_res_ObbScanner(JNIEnv* env);
extern int register_android_content_res_Configuration(JNIEnv* env);
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
+extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -1199,6 +1200,7 @@
REG_JNI(register_android_content_res_Configuration),
REG_JNI(register_android_animation_PropertyValuesHolder),
+ REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
};
/*
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4687ee0..3dcaa37 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -38,6 +38,12 @@
jfieldID surfaceTexture;
jfieldID facing;
jfieldID orientation;
+ jfieldID face_rect;
+ jfieldID face_score;
+ jfieldID rect_left;
+ jfieldID rect_top;
+ jfieldID rect_right;
+ jfieldID rect_bottom;
jmethodID post_event;
};
@@ -708,6 +714,35 @@
}
}
+static void android_hardware_Camera_startFaceDetection(JNIEnv *env, jobject thiz,
+ jint type, jobjectArray face)
+{
+ LOGV("startFaceDetection");
+ JNICameraContext* context;
+ sp<Camera> camera = get_native_camera(env, thiz, &context);
+ if (camera == 0) return;
+
+ status_t rc = camera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, type, 0);
+ if (rc == BAD_VALUE) {
+ char msg[64];
+ snprintf(msg, sizeof(msg), "invalid face detection type=%d", type);
+ jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+ } else if (rc != NO_ERROR) {
+ jniThrowRuntimeException(env, "start face detection failed");
+ }
+}
+
+static void android_hardware_Camera_stopFaceDetection(JNIEnv *env, jobject thiz)
+{
+ LOGV("stopFaceDetection");
+ sp<Camera> camera = get_native_camera(env, thiz, NULL);
+ if (camera == 0) return;
+
+ if (camera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0) != NO_ERROR) {
+ jniThrowRuntimeException(env, "stop face detection failed");
+ }
+}
+
//-------------------------------------------------
static JNINativeMethod camMethods[] = {
@@ -732,7 +767,7 @@
{ "startPreview",
"()V",
(void *)android_hardware_Camera_startPreview },
- { "stopPreview",
+ { "_stopPreview",
"()V",
(void *)android_hardware_Camera_stopPreview },
{ "previewEnabled",
@@ -777,6 +812,12 @@
{ "setDisplayOrientation",
"(I)V",
(void *)android_hardware_Camera_setDisplayOrientation },
+ { "_startFaceDetection",
+ "(I)V",
+ (void *)android_hardware_Camera_startFaceDetection },
+ { "_stopFaceDetection",
+ "()V",
+ (void *)android_hardware_Camera_stopFaceDetection},
};
struct field {
@@ -818,6 +859,12 @@
ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I", &fields.surfaceTexture },
{ "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing },
{ "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation },
+ { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect },
+ { "android/hardware/Camera$Face", "score", "I", &fields.face_score },
+ { "android/graphics/Rect", "left", "I", &fields.rect_left },
+ { "android/graphics/Rect", "top", "I", &fields.rect_top },
+ { "android/graphics/Rect", "right", "I", &fields.rect_right },
+ { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom },
};
if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index bd70dad..2929056 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -167,11 +167,11 @@
// ----------------------------------------------------------------------------
static int
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jint streamType, jint sampleRateInHertz, jint channels,
+ jint streamType, jint sampleRateInHertz, jint javaChannelMask,
jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession)
{
- LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
- sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
+ LOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d",
+ sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes);
int afSampleRate;
int afFrameCount;
@@ -184,11 +184,16 @@
return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
}
- if (!audio_is_output_channel(channels)) {
+ // Java channel masks don't map directly to the native definition, but it's a simple shift
+ // to skip the two deprecated channel configurations "default" and "mono".
+ uint32_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
+
+ if (!audio_is_output_channel(nativeChannelMask)) {
LOGE("Error creating AudioTrack: invalid channel mask.");
return AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
}
- int nbChannels = popcount(channels);
+
+ int nbChannels = popcount(nativeChannelMask);
// check the stream type
audio_stream_type_t atStreamType;
@@ -285,7 +290,7 @@
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
- channels,
+ nativeChannelMask,
frameCount,
0,// flags
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
@@ -306,7 +311,7 @@
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
- channels,
+ nativeChannelMask,
frameCount,
0,// flags
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 86e7cc0..41056fd 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -895,6 +895,18 @@
#endif
}
+static jboolean setDevicePropertyStringNative(JNIEnv *env, jobject object,
+ jstring path, jstring key, jstring value) {
+#ifdef HAVE_BLUETOOTH
+ const char *c_value = env->GetStringUTFChars(value, NULL);
+ jboolean ret = setDevicePropertyNative(env, object, path, key,
+ (void *)&c_value, DBUS_TYPE_STRING);
+ env->ReleaseStringUTFChars(value, (char *)c_value);
+ return ret;
+#else
+ return JNI_FALSE;
+#endif
+}
static jboolean createDeviceNative(JNIEnv *env, jobject object,
jstring address) {
@@ -1718,6 +1730,8 @@
(void *)cancelPairingUserInputNative},
{"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z",
(void *)setDevicePropertyBooleanNative},
+ {"setDevicePropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+ (void *)setDevicePropertyStringNative},
{"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative},
{"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative},
{"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative},
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index c152aa8..69c6021 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -641,7 +641,7 @@
/* name, signature, funcPtr */
{ "normalize", "(Z)J", (void*)android_text_format_Time_normalize },
{ "switchTimezone", "(Ljava/lang/String;)V", (void*)android_text_format_Time_switchTimezone },
- { "compare", "(Landroid/text/format/Time;Landroid/text/format/Time;)I", (void*)android_text_format_Time_compare },
+ { "nativeCompare", "(Landroid/text/format/Time;Landroid/text/format/Time;)I", (void*)android_text_format_Time_compare },
{ "format1", "(Ljava/lang/String;)Ljava/lang/String;", (void*)android_text_format_Time_format },
{ "format2445", "()Ljava/lang/String;", (void*)android_text_format_Time_format2445 },
{ "toString", "()Ljava/lang/String;", (void*)android_text_format_Time_toString },
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index 97f9fc3..5e668b9 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -45,11 +45,6 @@
};
static offsets_t offsets;
-static int gShortSize = -1;
-static int gLongSize = -1;
-static int gOldSize = -1;
-static int gNewSize = -1;
-
// ----------------------------------------------------------------------------
static void android_view_Display_init(
@@ -68,30 +63,6 @@
env->SetFloatField(clazz, offsets.ydpi, info.ydpi);
}
-static jint android_view_Display_getWidth(
- JNIEnv* env, jobject clazz)
-{
- DisplayID dpy = env->GetIntField(clazz, offsets.display);
- jint w = SurfaceComposerClient::getDisplayWidth(dpy);
- if (gShortSize > 0) {
- jint h = SurfaceComposerClient::getDisplayHeight(dpy);
- return w < h ? gShortSize : gLongSize;
- }
- return w == gOldSize ? gNewSize : w;
-}
-
-static jint android_view_Display_getHeight(
- JNIEnv* env, jobject clazz)
-{
- DisplayID dpy = env->GetIntField(clazz, offsets.display);
- int h = SurfaceComposerClient::getDisplayHeight(dpy);
- if (gShortSize > 0) {
- jint w = SurfaceComposerClient::getDisplayWidth(dpy);
- return h < w ? gShortSize : gLongSize;
- }
- return h == gOldSize ? gNewSize : h;
-}
-
static jint android_view_Display_getRawWidth(
JNIEnv* env, jobject clazz)
{
@@ -132,10 +103,6 @@
(void*)android_view_Display_getDisplayCount },
{ "init", "(I)V",
(void*)android_view_Display_init },
- { "getRealWidth", "()I",
- (void*)android_view_Display_getWidth },
- { "getRealHeight", "()I",
- (void*)android_view_Display_getHeight },
{ "getRawWidth", "()I",
(void*)android_view_Display_getRawWidth },
{ "getRawHeight", "()I",
@@ -156,24 +123,6 @@
int register_android_view_Display(JNIEnv* env)
{
- char buf[PROPERTY_VALUE_MAX];
- int len = property_get("persist.demo.screensizehack", buf, "");
- if (len > 0) {
- int temp1, temp2;
- if (sscanf(buf, "%dx%d", &temp1, &temp2) == 2) {
- if (temp1 < temp2) {
- gShortSize = temp1;
- gLongSize = temp2;
- } else {
- gShortSize = temp2;
- gLongSize = temp1;
- }
- } else if (sscanf(buf, "%d=%d", &temp1, &temp2) == 2) {
- gOldSize = temp1;
- gNewSize = temp2;
- }
- }
-
return AndroidRuntime::registerNativeMethods(env,
kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index b06de9d..b3f2d51 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -580,6 +580,11 @@
return renderer->getDisplayList(displayList);
}
+static jint android_view_GLES20Canvas_getDisplayListSize(JNIEnv* env,
+ jobject clazz, DisplayList* displayList) {
+ return displayList->getSize();
+}
+
static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
jobject clazz) {
return new DisplayListRenderer;
@@ -721,8 +726,7 @@
// ----------------------------------------------------------------------------
static void
-android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor)
-{
+android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
#ifdef USE_OPENGL_RENDERER
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
android::uirenderer::DisplayList::outputLogBuffer(fd);
@@ -814,6 +818,7 @@
{ "nGetDisplayList", "(II)I", (void*) android_view_GLES20Canvas_getDisplayList },
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
+ { "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListSize },
{ "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
{ "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
{ "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 0dc9293..4c1ca31 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -22,6 +22,7 @@
#include "android/graphics/GraphicsJNI.h"
#include <binder/IMemory.h>
+#include <gui/SurfaceTexture.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/Surface.h>
#include <ui/Region.h>
@@ -38,6 +39,7 @@
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <utils/misc.h>
@@ -244,6 +246,19 @@
setSurfaceControl(env, clazz, surface);
}
+static void Surface_initFromSurfaceTexture(
+ JNIEnv* env, jobject clazz, jobject jst)
+{
+ sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
+ sp<Surface> surface(new Surface(st));
+ if (surface == NULL) {
+ jniThrowException(env, OutOfResourcesException, NULL);
+ return;
+ }
+ setSurfaceControl(env, clazz, NULL);
+ setSurface(env, clazz, surface);
+}
+
static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
{
Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
@@ -761,10 +776,26 @@
return;
}
+ // The Java instance may have a SurfaceControl (in the case of the
+ // WindowManager or a system app). In that case, we defer to the
+ // SurfaceControl to send its ISurface. Otherwise, if the Surface is
+ // available we let it parcel itself. Finally, if the Surface is also
+ // NULL we fall back to using the SurfaceControl path which sends an
+ // empty surface; this matches legacy behavior.
const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
- SurfaceControl::writeSurfaceToParcel(control, parcel);
+ if (control != NULL) {
+ SurfaceControl::writeSurfaceToParcel(control, parcel);
+ } else {
+ sp<Surface> surface(Surface_getSurface(env, clazz));
+ if (surface != NULL) {
+ Surface::writeToParcel(surface, parcel);
+ } else {
+ SurfaceControl::writeSurfaceToParcel(NULL, parcel);
+ }
+ }
if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
- setSurfaceControl(env, clazz, 0);
+ setSurfaceControl(env, clazz, NULL);
+ setSurface(env, clazz, NULL);
}
}
@@ -784,6 +815,7 @@
{"nativeClassInit", "()V", (void*)nativeClassInit },
{"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
{"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
+ {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
{"getIdentity", "()I", (void*)Surface_getIdentity },
{"destroy", "()V", (void*)Surface_destroy },
{"release", "()V", (void*)Surface_release },
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
new file mode 100644
index 0000000..830f70e
--- /dev/null
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -0,0 +1,375 @@
+/*
+ * 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_TAG "NativeLibraryHelper"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/Log.h>
+#include <ScopedUtfChars.h>
+#include <utils/ZipFileRO.h>
+
+#include <zlib.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+
+#define APK_LIB "lib/"
+#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
+
+#define LIB_PREFIX "/lib"
+#define LIB_PREFIX_LEN (sizeof(LIB_PREFIX) - 1)
+
+#define LIB_SUFFIX ".so"
+#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
+
+#define GDBSERVER "gdbserver"
+#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
+
+#define TMP_FILE_PATTERN "/tmp.XXXXXX"
+#define TMP_FILE_PATTERN_LEN (sizeof(TMP_FILE_PATTERN) - 1)
+
+namespace android {
+
+typedef void (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
+
+// These match PackageManager.java install codes
+typedef enum {
+ INSTALL_SUCCEEDED = 0,
+ INSTALL_FAILED_INVALID_APK = -2,
+ INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
+} install_status_t;
+
+// Equivalent to isFilenameSafe
+static bool
+isFilenameSafe(const char* filename)
+{
+ off_t offset = 0;
+ for (;;) {
+ switch (*(filename + offset)) {
+ case 0:
+ // Null.
+ // If we've reached the end, all the other characters are good.
+ return true;
+
+ case 'A' ... 'Z':
+ case 'a' ... 'z':
+ case '0' ... '9':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+ case '/':
+ case '=':
+ case '_':
+ offset++;
+ break;
+
+ default:
+ // We found something that is not good.
+ return false;
+ }
+ }
+ // Should not reach here.
+}
+
+static bool
+isFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime,
+ long zipCrc, struct stat64* st)
+{
+ if (lstat64(filePath, st) < 0) {
+ // File is not found or cannot be read.
+ LOGV("Couldn't stat %s, copying: %s\n", filePath, strerror(errno));
+ return true;
+ }
+
+ if (!S_ISREG(st->st_mode)) {
+ return true;
+ }
+
+ if (st->st_size != fileSize) {
+ return true;
+ }
+
+ // For some reason, bionic doesn't define st_mtime as time_t
+ if (time_t(st->st_mtime) != modifiedTime) {
+ LOGV("mod time doesn't match: %ld vs. %ld\n", st->st_mtime, modifiedTime);
+ return true;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open(filePath, O_RDONLY));
+ if (fd < 0) {
+ LOGV("Couldn't open file %s: %s", filePath, strerror(errno));
+ return true;
+ }
+
+ long crc = crc32(0L, Z_NULL, 0);
+ unsigned char crcBuffer[16384];
+ ssize_t numBytes;
+ while ((numBytes = TEMP_FAILURE_RETRY(read(fd, crcBuffer, sizeof(crcBuffer)))) > 0) {
+ crc = crc32(crc, crcBuffer, numBytes);
+ }
+ close(fd);
+
+ LOGV("%s: crc = %lx, zipCrc = %lx\n", filePath, crc, zipCrc);
+
+ if (crc != zipCrc) {
+ return true;
+ }
+
+ return false;
+}
+
+static void
+sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
+{
+ size_t* total = (size_t*) arg;
+ size_t uncompLen;
+
+ if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) {
+ return;
+ }
+
+ *total += uncompLen;
+}
+
+/*
+ * Copy the native library if needed.
+ *
+ * This function assumes the library and path names passed in are considered safe.
+ */
+static void
+copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName)
+{
+ jstring* javaNativeLibPath = (jstring*) arg;
+ ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
+
+ size_t uncompLen;
+ long when;
+ long crc;
+ time_t modTime;
+
+ if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, &when, &crc)) {
+ return;
+ } else {
+ struct tm t;
+ ZipFileRO::zipTimeToTimespec(when, &t);
+ modTime = mktime(&t);
+ }
+
+ // Build local file path
+ const size_t fileNameLen = strlen(fileName);
+ char localFileName[nativeLibPath.size() + fileNameLen + 2];
+
+ if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) != nativeLibPath.size()) {
+ LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+ return;
+ }
+
+ *(localFileName + nativeLibPath.size()) = '/';
+
+ if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName, sizeof(localFileName)
+ - nativeLibPath.size() - 1) != fileNameLen) {
+ LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+ return;
+ }
+
+ // Only copy out the native file if it's different.
+ struct stat st;
+ if (!isFileDifferent(localFileName, uncompLen, modTime, crc, &st)) {
+ return;
+ }
+
+ char localTmpFileName[nativeLibPath.size() + TMP_FILE_PATTERN_LEN + 2];
+ if (strlcpy(localTmpFileName, nativeLibPath.c_str(), sizeof(localTmpFileName))
+ != nativeLibPath.size()) {
+ LOGD("Couldn't allocate local file name for library: %s", strerror(errno));
+ return;
+ }
+
+ *(localFileName + nativeLibPath.size()) = '/';
+
+ if (strlcpy(localTmpFileName + nativeLibPath.size(), TMP_FILE_PATTERN,
+ TMP_FILE_PATTERN_LEN - nativeLibPath.size()) != TMP_FILE_PATTERN_LEN) {
+ LOGI("Couldn't allocate temporary file name for library: %s", strerror(errno));
+ return;
+ }
+
+ int fd = mkstemp(localTmpFileName);
+ if (fd < 0) {
+ LOGI("Couldn't open temporary file name: %s: %s\n", localTmpFileName, strerror(errno));
+ return;
+ }
+
+ if (!zipFile->uncompressEntry(zipEntry, fd)) {
+ LOGI("Failed uncompressing %s to %s: %s", fileName, localTmpFileName, strerror(errno));
+ close(fd);
+ unlink(localTmpFileName);
+ return;
+ }
+
+ close(fd);
+
+ // Set the modification time for this file to the ZIP's mod time.
+ struct timeval times[2];
+ times[0].tv_sec = st.st_atime;
+ times[1].tv_sec = modTime;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ if (utimes(localTmpFileName, times) < 0) {
+ LOGI("Couldn't change modification time on %s: %s\n", localTmpFileName, strerror(errno));
+ unlink(localTmpFileName);
+ return;
+ }
+
+ // Set the mode to 755
+ static const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ if (chmod(localTmpFileName, mode) < 0) {
+ LOGI("Couldn't change permissions on %s: %s\n", localTmpFileName, strerror(errno));
+ unlink(localTmpFileName);
+ return;
+ }
+
+ // Finally, rename it to the final name.
+ if (rename(localTmpFileName, localFileName) < 0) {
+ LOGI("Couldn't rename %s to %s: %s\n", localTmpFileName, localFileName, strerror(errno));
+ unlink(localTmpFileName);
+ return;
+ }
+
+ LOGV("Successfully moved %s to %s\n", localTmpFileName, localFileName);
+}
+
+static install_status_t
+iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
+ iterFunc callFunc, void* callArg) {
+ ScopedUtfChars filePath(env, javaFilePath);
+ ScopedUtfChars cpuAbi(env, javaCpuAbi);
+ ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
+
+ ZipFileRO zipFile;
+
+ if (zipFile.open(filePath.c_str()) != NO_ERROR) {
+ LOGI("Couldn't open APK %s\n", filePath.c_str());
+ return INSTALL_FAILED_INVALID_APK;
+ }
+
+ const int N = zipFile.getNumEntries();
+
+ char fileName[PATH_MAX];
+
+ for (int i = 0; i < N; i++) {
+ const ZipEntryRO entry = zipFile.findEntryByIndex(i);
+ if (entry == NULL) {
+ continue;
+ }
+
+ // Make sure this entry has a filename.
+ if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) {
+ continue;
+ }
+
+ // Make sure we're in the lib directory of the ZIP.
+ if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
+ continue;
+ }
+
+ // Make sure the filename is at least to the minimum library name size.
+ const size_t fileNameLen = strlen(fileName);
+ static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
+ if (fileNameLen < minLength) {
+ continue;
+ }
+
+ const char* lastSlash = strrchr(fileName, '/');
+ if (lastSlash == NULL) {
+ LOG_ASSERT("last slash was null somehow for %s\n", fileName);
+ continue;
+ }
+
+ // Check to make sure the CPU ABI of this file is one we support.
+ const char* cpuAbiOffset = fileName + APK_LIB_LEN;
+ const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
+
+ LOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
+ if (cpuAbi.size() == cpuAbiRegionSize
+ && *(cpuAbiOffset + cpuAbi.size()) == '/'
+ && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
+ LOGV("Using ABI %s\n", cpuAbi.c_str());
+ } else if (cpuAbi2.size() == cpuAbiRegionSize
+ && *(cpuAbiOffset + cpuAbi2.size()) == '/'
+ && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
+ LOGV("Using ABI %s\n", cpuAbi2.c_str());
+ } else {
+ LOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
+ continue;
+ }
+
+ // If this is a .so file, check to see if we need to copy it.
+ if (!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
+ && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
+ && isFilenameSafe(lastSlash + 1)) {
+ callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
+ } else if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+ callFunc(env, callArg, &zipFile, entry, lastSlash + 1);
+ }
+ }
+
+ return INSTALL_SUCCEEDED;
+}
+
+static jint
+com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
+ jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
+{
+ return iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
+ copyFileIfChanged, &javaNativeLibPath);
+}
+
+static jlong
+com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
+ jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
+{
+ size_t totalSize = 0;
+
+ iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
+
+ return totalSize;
+}
+
+static JNINativeMethod gMethods[] = {
+ {"nativeCopyNativeBinaries",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+ (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
+ {"nativeSumNativeBinaries",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
+ (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
+};
+
+
+int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env)
+{
+ return AndroidRuntime::registerNativeMethods(env,
+ "com/android/internal/content/NativeLibraryHelper", gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 91003d1..92ba1d0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -393,8 +393,7 @@
android:description="@string/permdesc_nfc"
android:label="@string/permlab_nfc" />
- <!-- Allows applications to provide VPN functionality.
- @hide Pending API council approval -->
+ <!-- Allows applications to provide VPN functionality -->
<permission android:name="android.permission.VPN"
android:permissionGroup="android.permission-group.NETWORK"
android:protectionLevel="dangerous"
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
index 46194d8..9b78ae7 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
index fe11736..2860c68 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
index a11b128..7087cf7 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
index 40091d1..5d26dac 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
index 5b9a889..9531624 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
index 7f3426f..6b1eadc 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
index 9f57be8..671ca31 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
index 1a26bf6..b024da4 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
index 9e74f82..cba1ff5 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
index 8143700..62537b0 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
index c641801..5d559e1 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
index 895b61d..5041ff9 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
index c0ffb41..3492b8a 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
index 466adf2..49e837c 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index fc542d9..0d4e8b3 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index a5f8f93..c4283b6 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 8ea94e1..1b34672 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 8ea94e1..1b34672 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
index 6840962..71ae113 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index bee345e..739dff3 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index bee345e..26976c5 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
index b3196c3..9d787f1 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index e83686a..7699c47 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index e83686a..7699c47 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
index c44ae7a..1e9c9d2 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index 42e8ba4..27e7965 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index 42e8ba4..1dbabd3 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
index e240a2d..12eec10 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index a24b13b..5a94b8d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index a24b13b..5a94b8d 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
index 6df00f2..dc0c534 100644
--- a/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
index a63cdbb..2dd4548 100644
--- a/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
index 63015ec..d9fd48f 100644
--- a/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
index ca4dd76..7cec83a 100644
--- a/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
index daa47b7..9f3060d 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
index 6c45935..411f639 100644
--- a/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_away.png b/core/res/res/drawable-hdpi/presence_audio_away.png
index b26c0e0..c6af4f7 100644
--- a/core/res/res/drawable-hdpi/presence_audio_away.png
+++ b/core/res/res/drawable-hdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_busy.png b/core/res/res/drawable-hdpi/presence_audio_busy.png
index 0124659..ddba88d 100644
--- a/core/res/res/drawable-hdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-hdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_online.png b/core/res/res/drawable-hdpi/presence_audio_online.png
index 520bcd8..058963c 100644
--- a/core/res/res/drawable-hdpi/presence_audio_online.png
+++ b/core/res/res/drawable-hdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index 6a27382..4ef2821 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_busy.png b/core/res/res/drawable-hdpi/presence_busy.png
index 7278aec..391d1c9 100644
--- a/core/res/res/drawable-hdpi/presence_busy.png
+++ b/core/res/res/drawable-hdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_invisible.png b/core/res/res/drawable-hdpi/presence_invisible.png
index cff85be..8157010 100644
--- a/core/res/res/drawable-hdpi/presence_invisible.png
+++ b/core/res/res/drawable-hdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_offline.png b/core/res/res/drawable-hdpi/presence_offline.png
index 6c3fbb6..dc20b0f 100644
--- a/core/res/res/drawable-hdpi/presence_offline.png
+++ b/core/res/res/drawable-hdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_online.png b/core/res/res/drawable-hdpi/presence_online.png
index 77c368a..7694446 100644
--- a/core/res/res/drawable-hdpi/presence_online.png
+++ b/core/res/res/drawable-hdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_away.png b/core/res/res/drawable-hdpi/presence_video_away.png
index 302f538..0e9e384 100644
--- a/core/res/res/drawable-hdpi/presence_video_away.png
+++ b/core/res/res/drawable-hdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_busy.png b/core/res/res/drawable-hdpi/presence_video_busy.png
index 8fdea57..5b01840 100644
--- a/core/res/res/drawable-hdpi/presence_video_busy.png
+++ b/core/res/res/drawable-hdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_online.png b/core/res/res/drawable-hdpi/presence_video_online.png
index 6c1fd6b..fe285f5 100644
--- a/core/res/res/drawable-hdpi/presence_video_online.png
+++ b/core/res/res/drawable-hdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
index ff363f0..a2a6678 100644
--- a/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
index a5a0b98..733e852 100644
--- a/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
index 16742e8..e81e002 100644
--- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
index d6aa73b..1da2f90 100644
--- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
index ee3f4c2..8bbe6a0 100644
--- a/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
index 7c59e2f..d023d10 100644
--- a/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
index a1ef44c..fa6cb6f 100644
--- a/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
index 69e3ab7..00d577f 100644
--- a/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-hdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
index 031a54b..3bf750f 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
index 538e43c..d2dc269 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
index 3538aab..d38a140 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
index edc3f64..114e6f8 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
index 5434614..51512f5 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
index 0d43dc4..aebfa3e 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
index 64bda76..f653fae 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
index 39c9ea4..57192f2 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
index 6db6c5d..5435438 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
index 595261f..b350144 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
index f1129ef..5010bff 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
index c49dcc9..20f8d3d 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
index 423076c..96a9548 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
index e8b9a3b..8871519 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
index e33fbab..4738e5a 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
index 8fdb342..db93b6d 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index 6690f64..b47b5dd 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
index b7df43e..ad6947a 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 5ce7321..918f972 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 5ce7321..918f972 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
index 9a24b9c..1ae6cf2 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 34f69d3f..0514a7c 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index 34f69d3f..8cc4daf 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
index 93d9741..6449650 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 0629efe..7f44eae2 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index 0629efe..7f44eae2 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
index f462d98..3e9e6c3 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index a2f411e..9df36a2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index a2f411e..7abdfde 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
index 30373a6..df4927f 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index 231997a..cb70e35 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index 231997a..cb70e35 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
index 5ea5692..e37c559 100644
--- a/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
index 7b9805b..2ea9668 100644
--- a/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
index 83cb653..18a991f 100644
--- a/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
index bc7a117..28b9ec7 100644
--- a/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-mdpi/popup_inline_error_holo_dark.9.png
old mode 100755
new mode 100644
index 4092728..c3b8db9
--- a/core/res/res/drawable-mdpi/popup_inline_error_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-mdpi/popup_inline_error_holo_light.9.png
old mode 100755
new mode 100644
index 67a2cd4..c228a83
--- a/core/res/res/drawable-mdpi/popup_inline_error_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_away.png b/core/res/res/drawable-mdpi/presence_audio_away.png
index cb30b32..e68bc11 100644
--- a/core/res/res/drawable-mdpi/presence_audio_away.png
+++ b/core/res/res/drawable-mdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_busy.png b/core/res/res/drawable-mdpi/presence_audio_busy.png
index 40f168c..caa6d06 100644
--- a/core/res/res/drawable-mdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-mdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_online.png b/core/res/res/drawable-mdpi/presence_audio_online.png
index 3faede8..a740598 100644
--- a/core/res/res/drawable-mdpi/presence_audio_online.png
+++ b/core/res/res/drawable-mdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_away.png b/core/res/res/drawable-mdpi/presence_away.png
index a777440..62ee0ca 100644
--- a/core/res/res/drawable-mdpi/presence_away.png
+++ b/core/res/res/drawable-mdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_busy.png b/core/res/res/drawable-mdpi/presence_busy.png
index d33d0f0..6def876 100644
--- a/core/res/res/drawable-mdpi/presence_busy.png
+++ b/core/res/res/drawable-mdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_invisible.png b/core/res/res/drawable-mdpi/presence_invisible.png
index 527e97c..715a164 100644
--- a/core/res/res/drawable-mdpi/presence_invisible.png
+++ b/core/res/res/drawable-mdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_offline.png b/core/res/res/drawable-mdpi/presence_offline.png
index 4320963..262d530 100644
--- a/core/res/res/drawable-mdpi/presence_offline.png
+++ b/core/res/res/drawable-mdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_online.png b/core/res/res/drawable-mdpi/presence_online.png
index b41e8d9..e16ec81 100644
--- a/core/res/res/drawable-mdpi/presence_online.png
+++ b/core/res/res/drawable-mdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_away.png b/core/res/res/drawable-mdpi/presence_video_away.png
index b56275f..2d3508d 100644
--- a/core/res/res/drawable-mdpi/presence_video_away.png
+++ b/core/res/res/drawable-mdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_busy.png b/core/res/res/drawable-mdpi/presence_video_busy.png
index f1cf238..f317efa 100644
--- a/core/res/res/drawable-mdpi/presence_video_busy.png
+++ b/core/res/res/drawable-mdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_online.png b/core/res/res/drawable-mdpi/presence_video_online.png
index 10bbd74..777b6ff 100644
--- a/core/res/res/drawable-mdpi/presence_video_online.png
+++ b/core/res/res/drawable-mdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
index 2703553..537ab8c 100644
--- a/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
index 87d2c87..cee54b7 100644
--- a/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
index 3c97355..67fb438 100644
--- a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
index 96155e3..25beedd 100644
--- a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
index 26dcfbf..ed446d6 100644
--- a/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
index 49dad0c..08b2dcd 100644
--- a/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
index ebccabd..2d5e5a1 100644
--- a/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
index 37d3f58..2edad73 100644
--- a/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
+++ b/core/res/res/drawable-mdpi/spinner_76_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off.png b/core/res/res/drawable-xhdpi/btn_check_off.png
new file mode 100644
index 0000000..083e04a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable.png b/core/res/res/drawable-xhdpi/btn_check_off_disable.png
new file mode 100644
index 0000000..e746557
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png
new file mode 100644
index 0000000..377b645
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png
new file mode 100644
index 0000000..df66e7e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png
new file mode 100644
index 0000000..96b2a0f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png
new file mode 100644
index 0000000..df66e7e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png
new file mode 100644
index 0000000..96b2a0f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..0f34797
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png
new file mode 100644
index 0000000..95f8a15
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png
new file mode 100644
index 0000000..26a4540
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png
new file mode 100644
index 0000000..803f0af
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png
new file mode 100644
index 0000000..9a3e472
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png
new file mode 100644
index 0000000..dce8e06
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo.png b/core/res/res/drawable-xhdpi/btn_check_off_holo.png
new file mode 100644
index 0000000..bdab4d0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png
new file mode 100644
index 0000000..f8afd6a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png
new file mode 100644
index 0000000..902b3a5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png
new file mode 100644
index 0000000..ee19faf
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png
new file mode 100644
index 0000000..ea7dec8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed.png
new file mode 100644
index 0000000..a3065f6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png
new file mode 100644
index 0000000..575f4e8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png
new file mode 100644
index 0000000..8d5d780
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_selected.png b/core/res/res/drawable-xhdpi/btn_check_off_selected.png
new file mode 100644
index 0000000..edfb30a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on.png b/core/res/res/drawable-xhdpi/btn_check_on.png
new file mode 100644
index 0000000..c1dee18
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disable.png b/core/res/res/drawable-xhdpi/btn_check_on_disable.png
new file mode 100644
index 0000000..179f191
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..02e4254
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png
new file mode 100644
index 0000000..7e61802
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png
new file mode 100644
index 0000000..cc6326e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png
new file mode 100644
index 0000000..f468781
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png
new file mode 100644
index 0000000..1e25364
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png
new file mode 100644
index 0000000..fc1af9f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo.png b/core/res/res/drawable-xhdpi/btn_check_on_holo.png
new file mode 100644
index 0000000..75f66521
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png
new file mode 100644
index 0000000..c327f56
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png
new file mode 100644
index 0000000..74a2ea3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png
new file mode 100644
index 0000000..f84a5b0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
new file mode 100644
index 0000000..48a6431
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
new file mode 100644
index 0000000..5defddf
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_selected.png b/core/res/res/drawable-xhdpi/btn_check_on_selected.png
new file mode 100644
index 0000000..963c68e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..eb7ce5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..eb7ce5e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
new file mode 100644
index 0000000..4e4d3d4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
new file mode 100644
index 0000000..ee291b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
new file mode 100644
index 0000000..83e5011
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
new file mode 100644
index 0000000..67f007a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
new file mode 100644
index 0000000..4764d1b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
new file mode 100644
index 0000000..4764d1b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
new file mode 100644
index 0000000..9f18a87
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
new file mode 100644
index 0000000..652aa3e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
new file mode 100644
index 0000000..92a7664
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
new file mode 100644
index 0000000..b949121
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
new file mode 100644
index 0000000..6a35514
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
new file mode 100644
index 0000000..9068d75
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
new file mode 100644
index 0000000..3f42693
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
new file mode 100644
index 0000000..daac2e1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
new file mode 100644
index 0000000..94f1a5a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
new file mode 100644
index 0000000..94f1a5a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
new file mode 100644
index 0000000..ecdc72b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
new file mode 100644
index 0000000..f823033
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
new file mode 100644
index 0000000..f537a6d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
new file mode 100644
index 0000000..1b11689
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
new file mode 100644
index 0000000..787ba9e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
new file mode 100644
index 0000000..74a156f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
new file mode 100644
index 0000000..44860dc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_default_transparent_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png
new file mode 100644
index 0000000..8005de7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_close_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png
new file mode 100644
index 0000000..333dd24d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_close_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png
new file mode 100644
index 0000000..4a56a80
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_open_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png
new file mode 100644
index 0000000..67ed4c0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_open_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_input_error.png b/core/res/res/drawable-xhdpi/indicator_input_error.png
new file mode 100644
index 0000000..5be92a0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/indicator_input_error.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..d69b772
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..a210f3c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..f106329
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-xhdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..0c65386
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_away.png b/core/res/res/drawable-xhdpi/presence_audio_away.png
new file mode 100644
index 0000000..4fc6f6a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_busy.png b/core/res/res/drawable-xhdpi/presence_audio_busy.png
new file mode 100644
index 0000000..ca45ac9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_audio_online.png b/core/res/res/drawable-xhdpi/presence_audio_online.png
new file mode 100644
index 0000000..595c730
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_away.png b/core/res/res/drawable-xhdpi/presence_away.png
new file mode 100644
index 0000000..1478e72
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_busy.png b/core/res/res/drawable-xhdpi/presence_busy.png
new file mode 100644
index 0000000..8278ce2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_invisible.png b/core/res/res/drawable-xhdpi/presence_invisible.png
new file mode 100644
index 0000000..9bb6cef
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_offline.png b/core/res/res/drawable-xhdpi/presence_offline.png
new file mode 100644
index 0000000..fc7ba24
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_online.png b/core/res/res/drawable-xhdpi/presence_online.png
new file mode 100644
index 0000000..e2aef11
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_away.png b/core/res/res/drawable-xhdpi/presence_video_away.png
new file mode 100644
index 0000000..02f7d63
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_busy.png b/core/res/res/drawable-xhdpi/presence_video_busy.png
new file mode 100644
index 0000000..db0bec7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/presence_video_online.png b/core/res/res/drawable-xhdpi/presence_video_online.png
new file mode 100644
index 0000000..e12be95
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
new file mode 100644
index 0000000..f868ff1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_16_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
new file mode 100644
index 0000000..abd2d57
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_16_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
new file mode 100644
index 0000000..d2691d3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
new file mode 100644
index 0000000..a5c87d1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
new file mode 100644
index 0000000..24176bf
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_48_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
new file mode 100644
index 0000000..53b34ef
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_48_outer_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
new file mode 100644
index 0000000..fa267b4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_76_inner_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
new file mode 100644
index 0000000..2c1f879
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_76_outer_holo.png
Binary files differ
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 6579e76..99ab8a3 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -83,16 +83,6 @@
android:layout_weight="1"
/>
- <!-- 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="28dip"
- android:visibility="gone"
- />
-
<!-- emergency call button NOT CURRENTLY USED -->
<Button
android:id="@+id/emergencyCallButton"
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 c63b0ff..64c002f 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -75,16 +75,6 @@
android:layout_marginBottom="80dip"
/>
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
- android:layout_width="match_parent"
- android:layout_height="230dip"
- android:background="@drawable/password_keyboard_background_holo"
- android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- android:keyTextSize="28dip"
- android:visibility="gone"
- />
-
<!-- emergency call button -->
<Button
android:id="@+id/emergencyCallButton"
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 302ee01..f3850d5 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml
@@ -114,19 +114,6 @@
</LinearLayout>
- <!-- Status2 is generally charge 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"
- />
-
<!-- Status1 is generally battery status and informational messages -->
<TextView
android:id="@+id/status1"
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 53fe902..f4c99f1 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml
@@ -113,19 +113,6 @@
</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"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index 543747f..d32cd0c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -45,13 +45,12 @@
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
- android:orientation="vertical"
- >
+ android:orientation="vertical">
+
<TextView
android:id="@+id/screenLocked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/status2"
android:layout_marginLeft="24dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginTop="12dip"
@@ -65,23 +64,7 @@
android:layout_gravity="center"
/>
- <!-- "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"
- android:visibility="gone"
- />
-
- <!-- 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"
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 37bb522..07b4837 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -61,19 +61,6 @@
android:layout_alignParentTop="true"
android:drawablePadding="4dip"/>
- <!-- "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_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_marginTop="12dip"
- android:text="@string/emergency_calls_only"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/white"/>
-
-
<com.android.internal.widget.WaveView
android:id="@+id/unlock_widget"
android:layout_width="wrap_content"
@@ -82,7 +69,6 @@
android:layout_marginRight="0dip"
android:layout_weight="1.0"/>
-
<!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
<Button
android:id="@+id/emergencyCallButton"
diff --git a/core/res/res/layout/activity_chooser_view.xml b/core/res/res/layout/activity_chooser_view.xml
index 50b1878..5d82a97 100644
--- a/core/res/res/layout/activity_chooser_view.xml
+++ b/core/res/res/layout/activity_chooser_view.xml
@@ -20,12 +20,52 @@
android:id="@+id/activity_chooser_view_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
style="?android:attr/actionButtonStyle">
- <ImageButton android:id="@+id/default_activity_button"
- style="@style/Widget.ActivityChooserViewButton" />
+ <FrameLayout
+ android:id="@+id/default_activity_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:focusable="true"
+ android:addStatesFromChildren="true"
+ android:background="?android:attr/selectableItemBackground">
- <ImageButton android:id="@+id/expand_activities_button"
- style="@style/Widget.ActivityChooserViewButton" />
+ <ImageView android:id="@+id/image"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:layout_gravity="center"
+ android:layout_marginTop="4dip"
+ android:layout_marginBottom="4dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true" />
+
+ </FrameLayout>
+
+ <FrameLayout
+ android:id="@+id/expand_activities_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:focusable="true"
+ android:addStatesFromChildren="true"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView android:id="@+id/image"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:layout_gravity="center"
+ android:layout_marginTop="4dip"
+ android:layout_marginBottom="4dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
+ android:scaleType="fitCenter"
+ android:adjustViewBounds="true" />
+
+ </FrameLayout>
</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index e867fe0..960907d 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -24,7 +24,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:rowCount="10"
+ android:rowCount="7"
android:id="@+id/root"
android:clipChildren="false">
@@ -95,33 +95,7 @@
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:layout_rowFlexibility="canStretch"
- android:layout_columnFlexibility="canStretch"
- />
+ <Space android:layout_gravity="fill" />
<TextView
android:id="@+id/carrier"
@@ -133,19 +107,6 @@
android:textColor="?android:attr/textColorSecondary"
/>
- <!-- "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"
- />
-
<Button
android:id="@+id/emergencyCallButton"
android:layout_gravity="right"
@@ -157,13 +118,13 @@
/>
<!-- Column 1 -->
- <Space android:layout_width="32dip" android:layout_rowSpan="10" />
+ <Space android:layout_width="32dip" android:layout_rowSpan="7" />
<!-- Column 2 - password entry field and PIN keyboard -->
<LinearLayout
android:orientation="vertical"
android:layout_gravity="center|fill"
- android:layout_rowSpan="10">
+ android:layout_rowSpan="7">
<EditText android:id="@+id/passwordEntry"
android:layout_height="wrap_content"
@@ -177,6 +138,7 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:background="@drawable/lockscreen_password_field_dark"
android:textColor="?android:attr/textColorPrimary"
+ android:imeOptions="flagNoFullscreen"
/>
<!-- Numeric keyboard -->
@@ -187,9 +149,19 @@
android:background="#40000000"
android:layout_marginTop="5dip"
android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- android:visibility="visible"
+ android:visibility="gone"
/>
</LinearLayout>
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="5"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index 6953ac8..7a51035 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -16,38 +16,85 @@
** limitations under the License.
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<GridLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:gravity="center_horizontal">
- <!-- top: status -->
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginRight="16dip">
- <include layout="@layout/keyguard_screen_status_port"
+ <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_alignParentRight="true"/>
- </RelativeLayout>
+ 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="@*android:color/lockscreen_clock_background"
+ />
- <!-- emergency call button -->
- <Button
- android:id="@+id/emergencyCallButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="4dip"
- android:layout_marginRight="16dip"
+ <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"
+ />
+
+ </com.android.internal.widget.DigitalClock>
+
+ <LinearLayout
+ android:orientation="horizontal"
android:layout_gravity="right"
- android:drawableLeft="@drawable/lockscreen_emergency_button"
- android:drawablePadding="8dip"
- android:text="@string/lockscreen_emergency_call"
- style="?android:attr/buttonBarButtonStyle"
- />
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
- <!-- bottom: password -->
+ <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:layout_marginLeft="16dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
+ 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"
+ />
+
+ <Space android:layout_height="100dip"/>
<!-- Password entry field -->
<EditText android:id="@+id/passwordEntry"
@@ -64,27 +111,14 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#ffffffff"/>
- <View
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- />
+ <Space android:layout_gravity="fill" />
<!-- Numeric keyboard -->
<com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
android:layout_width="match_parent"
android:layout_height="260dip"
android:background="#40000000"
- android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- />
-
- <!-- Alphanumeric keyboard -->
- <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
- android:layout_width="match_parent"
- android:layout_height="400dip"
- android:background="@drawable/password_keyboard_background_holo"
- android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
- android:keyTextSize="22dip"
+ android:keyBackground="@*android:drawable/btn_keyboard_key_fulltrans"
android:visibility="gone"
/>
@@ -93,7 +127,6 @@
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"
@@ -101,4 +134,28 @@
android:ellipsize="marquee"
/>
-</LinearLayout>
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dip"
+ android:layout_marginRight="16dip"
+ android:layout_gravity="center_horizontal"
+ android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
+ style="?android:attr/buttonBarButtonStyle"
+ android:drawablePadding="4dip"
+ android:text="@*android:string/lockscreen_emergency_call"
+ android:visibility="gone"
+ />
+
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="4"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
+</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_status_land.xml b/core/res/res/layout/keyguard_screen_status_land.xml
deleted file mode 100644
index 021faa3..0000000
--- a/core/res/res/layout/keyguard_screen_status_land.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-
-<!-- Status to show on the left side of lock screen -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="left"
- >
-
- <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="@dimen/keyguard_lockscreen_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/lockscreen_clock_background"
- android:layout_marginBottom="6dip"
- />
-
- <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:textColor="@color/lockscreen_clock_foreground"
- android:layout_alignLeft="@id/timeDisplayBackground"
- android:layout_alignTop="@id/timeDisplayBackground"
- android:layout_marginBottom="6dip"
- />
-
- </com.android.internal.widget.DigitalClock>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/time"
- android:layout_marginTop="10dip">
-
- <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:layout_marginLeft="30dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/>
-
- </LinearLayout>
-
- <!-- Status2 is generally charge status -->
- <TextView
- android:id="@+id/status2"
- 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="@dimen/keyguard_lockscreen_status_line_font_size"
- android:layout_marginTop="10dip"
- android:drawablePadding="4dip"
- android:visibility="gone"
- />
-
- <!-- Status1 is generally battery status and informational messages -->
- <TextView
- android:id="@+id/status1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dip"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
-
-</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_status_port.xml b/core/res/res/layout/keyguard_screen_status_port.xml
deleted file mode 100644
index f84e61c..0000000
--- a/core/res/res/layout/keyguard_screen_status_port.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-
-<!-- Status to show on the left side of lock screen -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="left">
-
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- 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... -->
- <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:textColor="@color/lockscreen_clock_background"
- android:layout_marginBottom="6dip"
- />
-
- <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:textColor="@color/lockscreen_clock_foreground"
- android:layout_marginBottom="6dip"
- android:layout_alignLeft="@id/timeDisplayBackground"
- android:layout_alignTop="@id/timeDisplayBackground"
- />
-
- </com.android.internal.widget.DigitalClock>
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/time"
- 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="@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="16dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"/>
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/status1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- 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/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:layout_alignParentTop="true"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:layout_marginTop="4dip"
- android:drawablePadding="4dip"
- android:visibility="gone"
- />
-
-
-</LinearLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 1e2abf9..05c768d 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -21,21 +21,17 @@
state of the device, as well as instructions on how to get past it
depending on the state of the device. It is the same for landscape
and portrait.-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<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"
- android:id="@+id/root"
- android:clipChildren="false">
+ android:gravity="center_horizontal">
- <!-- time and date -->
<com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_marginRight="16dip"
- android:layout_marginTop="48dip"
- android:layout_marginLeft="20dip">
+ 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... -->
@@ -65,16 +61,10 @@
</com.android.internal.widget.DigitalClock>
- <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="16dip"
- android:layout_marginRight="16dip"
- android:layout_marginTop="16dip"
- android:layout_alignParentRight="true"
- android:gravity="right"
- android:orientation="horizontal">
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_gravity="right"
+ android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
<TextView
android:id="@+id/date"
@@ -90,25 +80,20 @@
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="@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/date_alarm_status_container"
- android:layout_marginTop="4dip"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:layout_alignParentRight="true"
+ 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"
@@ -116,39 +101,7 @@
android:drawablePadding="4dip"
/>
- <TextView
- android:id="@+id/status2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/status1"
- android:layout_marginTop="4dip"
- 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
- android:id="@+id/screenLocked"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/status2"
- 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"
- />
+ <Space android:layout_gravity="fill" />
<!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
<Button
@@ -157,26 +110,23 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dip"
android:layout_marginRight="16dip"
- android:drawableLeft="@drawable/lockscreen_emergency_button"
- android:layout_alignParentRight="true"
- android:layout_below="@id/screenLocked"
+ android:layout_gravity="right"
+ android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
style="?android:attr/buttonBarButtonStyle"
android:drawablePadding="4dip"
- android:text="@string/lockscreen_emergency_call"
- android:visibility="visible"
+ android:text="@*android:string/lockscreen_emergency_call"
+ android:visibility="gone"
/>
<RelativeLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:gravity="center_horizontal">
+ android:layout_height="292dip">
<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_height="match_parent"
android:layout_alignParentBottom="true"
android:targetDrawables="@array/lockscreen_targets_when_silent"
@@ -206,24 +156,39 @@
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>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ style="?android:attr/buttonBarStyle"
+ android:gravity="center"
+ android:weightSum="2">
+
+ <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="@*android:string/lockscreen_emergency_call"
+ android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
+ android:drawablePadding="0dip"
+ android:visibility="gone"
+ />
+
+ </LinearLayout>
+
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="4"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
+</GridLayout>
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 7aab04e..6440726 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -24,13 +24,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:rowCount="8"
+ android:rowCount="7"
android:id="@+id/root"
android:clipChildren="false">
<!-- Column 0 -->
<com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_marginTop="8dip"
+ android:layout_marginTop="80dip"
android:layout_marginBottom="8dip"
android:layout_gravity="right">
@@ -95,89 +95,41 @@
android:layout_gravity="right"
/>
+ <Space android:layout_gravity="fill" />
+
<TextView
- android:id="@+id/status2"
- android:layout_marginTop="4dip"
+ android:id="@+id/carrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_gravity="right"
+ android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
+ android:text="@*android:string/lockscreen_emergency_call"
+ style="?android:attr/buttonBarButtonStyle"
+ android:drawablePadding="8dip"
+ android:visibility="gone"
/>
- <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:layout_rowFlexibility="canStretch"
- android:layout_columnFlexibility="canStretch"
- />
-
- <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: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"
- />
-
- <!-- "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_alignParentTop="true"
- android:layout_marginTop="20dip"
- 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"
- android:layout_gravity="right"
- />
-
- <Button
- android:id="@+id/emergencyCallButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- 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>
-
<!-- Column 1 -->
- <Space android:layout_width="32dip" android:layout_rowSpan="8" />
+ <Space android:layout_width="64dip" android:layout_rowSpan="7" />
<!-- Column 2 -->
<com.android.internal.widget.multiwaveview.MultiWaveView
android:id="@+id/unlock_widget"
android:layout_width="200dip"
android:layout_height="match_parent"
- android:layout_rowSpan="8"
+ android:layout_rowSpan="7"
android:targetDrawables="@array/lockscreen_targets_when_silent"
android:handleDrawable="@drawable/ic_lockscreen_handle"
@@ -192,4 +144,14 @@
android:verticalOffset="0dip"
/>
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="5"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 8f083a0..c425b73 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -90,11 +90,7 @@
android:layout_gravity="right"
/>
- <!-- TODO: remove hard coded height since layout_rowWeight doesn't seem to be working -->
- <Space
- android:layout_rowFlexibility="canStretch"
- android:layout_columnFlexibility="canStretch"
- />
+ <Space android:layout_gravity="fill" />
<TextView android:id="@+id/carrier"
android:layout_gravity="right"
@@ -135,6 +131,7 @@
</LinearLayout>
<!-- Column 1: lock pattern -->
+
<com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -144,4 +141,15 @@
android:layout_marginLeft="8dip"
android:layout_rowSpan="7"/>
+
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="5"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
</GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 35fd473..433dda7 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -27,7 +27,6 @@
android:layout_height="match_parent"
android:gravity="center_horizontal">
-
<com.android.internal.widget.DigitalClock android:id="@+id/time"
android:layout_marginBottom="18dip"
android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
@@ -100,17 +99,7 @@
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"
- />
+ <Space android:layout_gravity="fill" />
<!-- 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
@@ -125,7 +114,6 @@
android:layout_marginBottom="4dip"
android:layout_marginLeft="8dip"
android:layout_gravity="center|bottom"
- android:layout_rowFlexibility="canStretch"
/>
<TextView
@@ -171,4 +159,14 @@
</LinearLayout>
+ <!-- Music transport control -->
+ <include android:id="@+id/transport"
+ layout="@layout/keyguard_transport_control"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_rowSpan="4"
+ android:layout_columnSpan="1"
+ android:layout_gravity="fill"
+ />
+
</GridLayout>
diff --git a/core/res/res/layout/keyguard_transport_control.xml b/core/res/res/layout/keyguard_transport_control.xml
new file mode 100644
index 0000000..6308b02
--- /dev/null
+++ b/core/res/res/layout/keyguard_transport_control.xml
@@ -0,0 +1,53 @@
+<?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.
+*/
+-->
+
+<com.android.internal.widget.TransportControlView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:gravity="bottom"
+ android:orientation="horizontal"
+ android:background="#a0808080"
+ android:visibility="gone">
+
+ <Button android:id="@+id/control_prev"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="#80ff0000"
+ />
+
+ <Space android:layout_width="0dip"
+ android:layout_height="0dip"
+ android:layout_weight="1"/>
+
+ <Button android:id="@+id/control_pauseplay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="#8000ff00"
+ />
+
+ <Space android:layout_width="0dip"
+ android:layout_height="0dip"
+ android:layout_weight="1"/>
+
+ <Button android:id="@+id/control_next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="#800000ff"
+ />
+
+</com.android.internal.widget.TransportControlView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 6d9f2fe..e60af6d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -385,6 +385,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Laat programme toe om te sien watter sleutels jy druk, selfs wanneer jy met \'n ander program werk (soos wanneer jy \'n wagwoord intik). Behoort vir gewone programme nooit nodig te wees nie."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"bind aan \'n invoermetode"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Laat die houer toe om aan die topvlak-koppelvlak van \'n invoermetode te bind. Behoort vir gewone programme nooit nodig te wees nie."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind aan \'n muurpapier"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Stel die houer toe om aan die topvlak-koppelvlak van \'n muurpapier te bind. Behoort vir gewone programme nooit nodig te wees nie."</string>
<!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -962,6 +966,10 @@
<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>
<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>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<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) -->
@@ -1216,6 +1224,22 @@
<item quantity="one" msgid="1634101450343277345">"Oop Wi-Fi-netwerke beskikbaar"</item>
<item quantity="other" msgid="7915895323644292768">"Oop Wi-Fi-netwerke beskikbaar"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Voeg karakter in"</string>
<!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
<skip />
@@ -1277,6 +1301,8 @@
<skip />
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<!-- no translation found for usb_notification_message (4447869605109736382) -->
<skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formateer USB-berging"</string>
@@ -1465,4 +1491,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 9fff387..716d19f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -385,6 +385,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"ትግበራዎች ከሌላ ትግበራዎች ጋር እንኳ ሲገናኙ የሚጫኑትን ቁልፎች ለመመልከት ይፈቅዳሉ።ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"በግቤት ሜተድ ጠርዝ"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"ያዡ ግቤት ሜተዱን ወደ ከፍተኛ-ደረጃ በይነገጽ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"በልጣፍ ጠርዝ"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"ያዡ ግቤት ሜተዱን ወደ ከፍተኛ-ደረጃ ልጣፍ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
<!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -962,6 +966,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"ትግበራ በስልክዎ ላይ የተከማቹትንታሪኮች እና ዕልባቶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች የቀን መቁጠሪያዎን ለማጥፋት ወይም ለመቀየር ይህን መጠቀም ይችላሉ።"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"በማንቂያ ሰዓት ውስጥ ማንቂያ አዘጋጅ"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"ትግበራ በተጫነ የማንቂያ ሰዓት ትግበራ ማንቂያ ለማዘጋጀትይፈቅዳል። አንዳንድ የማንቂያ ሰዓት ትግበራዎች ይህን ገፅታ ላይተገብሩ ይችላሉ።"</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"የአሳሽ ገፀ ሥፍራ ፍቃዶችን ቀይር"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ትግበራ የአሳሹን ገፀ ሥፍራ ፈቃዶች ለመቀየር ይፈቅዳል። ተንኮል አዘል ትግበራዎች ይህን በመጠቀም የሥፍራ መረጃን ወደ ድረ ገፆች ለመላክ ይችላሉ።"</string>
<!-- no translation found for save_password_message (767344687139195790) -->
@@ -1216,6 +1224,22 @@
<item quantity="one" msgid="1634101450343277345">"አውታረ መረብ ሲኖር Wi-Fi ክፈት"</item>
<item quantity="other" msgid="7915895323644292768">"አውታረ መረቦች ሲኖሩ Wi-Fi ክፈት"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"ቁምፊ አስገባ"</string>
<!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
<skip />
@@ -1277,6 +1301,8 @@
<skip />
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<!-- no translation found for usb_notification_message (4447869605109736382) -->
<skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"የUSB ማከማቻ ቅረፅ"</string>
@@ -1465,4 +1491,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 70fc500..12a240a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"للسماح للتطبيقات بمراقبة الأحرف التي تضغط عليها حتى عند التفاعل مع تطبيق آخر (مثل إدخال كلمة مرور). لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"الالتزام بطريقة إرسال ما"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لطريقة الإرسال. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"الالتزام بخلفية ما"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للخلفية. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"الإقليم"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"الرمز البريدي"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"الولاية"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"الرمز البريدي"</string>
+ <string name="autofill_county" msgid="237073771020362891">"المقاطعة"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"جزيرة"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"المنطقة"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"القسم"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"المحافظة"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"الدائرة"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"المنطقة"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"الإمارة"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"قراءة سجل المتصفح والإشارات"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"للسماح للتطبيق بقراءة جميع عناوين URL التي انتقل إليها المتصفح. وجميع إشارات المتصفح."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"كتابة سجل المتصفح والإشارات"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"للسماح لتطبيق ما بتعديل سجل المتصفح أو الإشارات في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات المتصفح أو تعديلها."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"تعيين المنبه في ساعة المنبه"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"للسماح للتطبيق بضبط المنبه في تطبيق ساعة منبه مثبّت. ربما لا تنفذ بعض تطبيقات المنبه هذه الميزة."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"تعديل أذونات الموقع الجغرافي للمتصفح"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"للسماح لتطبيق ما بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع ويب عشوائية."</string>
<string name="save_password_message" msgid="767344687139195790">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"هناك شبكة Wi-Fi مفتوحة متاحة"</item>
<item quantity="other" msgid="7915895323644292768">"هناك شبكات Wi-Fi مفتوحة متاحة"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"إدراج حرف"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"تطبيق غير معروف"</string>
<string name="sms_control_title" msgid="7296612781128917719">"إرسال رسائل قصيرة SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"التوصيل كجهاز وسائط"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"التوصيل ككاميرا"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"التوصيل كأداة تثبيت"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"المس للاطلاع على خيارات USB الأخرى"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"بصمة أصبع SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"بصمة أصبع SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"عرض الكل..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"تحديد نشاط"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"مشاركة مع..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b67812a..f20ef1b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Разрешава на приложенията да наблюдават кои клавиши натискате дори и когато взаимодействате с друго приложение (например когато въвеждате парола). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"обвързване с метод на въвеждане"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на метод на въвеждане. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"обвързване с тапет"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на тапет. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Провинция"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Пощенски код"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Щат"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Пощенски код"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Окръг"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Остров"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Област"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Департамент"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Община"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Район"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Емирство"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"четене на историята и отметките на браузъра"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешава на приложението да чете всички URL адреси, посетени от браузъра, и всички негови отметки."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис в историята и отметките на браузъра"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени на телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят данните на браузъра ви."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"навиване на будилника"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Промяна на разрешенията за местоположение в браузъра"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string>
<string name="save_password_message" msgid="767344687139195790">"Искате ли браузърът да запомни тази парола?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Има достъпна отворена Wi-Fi мрежа"</item>
<item quantity="other" msgid="7915895323644292768">"Има достъпни отворени Wi-Fi мрежи"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Вмъкване на знак"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Неизвестно приложение"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Изпращане на SMS съобщения"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Свързан като медийно устройство"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Свързан като камера"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Свързан като инсталационна програма"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Докоснете за други опции за USB"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c7b1735..cb57c33 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permet a les aplicacions fer un seguiment de les tecles que premeu, fins i tot quan s\'interactua amb una altra aplicació (com ara introduir una contrasenya). No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a un mètode d\'entrada"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permet al titular vincular amb la interfície de nivell superior d\'un mètode d\'entrada. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un empaperat"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permet al titular vincular amb la interfície de nivell superior d\'un empaperat. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Província"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Codi postal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Estat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Codi postal"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Comtat"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Illa"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Districte"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Districte"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Àrea"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"llegir l\'historial i les adreces d\'interès del navegador"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permet a l\'aplicació llegir tots els URL que ha visitat el navegador i totes les adreces d\'interès del navegador."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escriure l\'historial i les adreces d\'interès del navegador"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet a una aplicació modificar l\'historial o les adreces d\'interès del navegador emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades del navegador."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"defineix l\'alarma com a despertador"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica els permisos d\'ubicació geogràfica del navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet a una aplicació modificar els permisos d\'ubicació geogràfica del navegador. Les aplicacions malicioses poden utilitzar-ho per permetre l\'enviament d\'informació d\'ubicació a llocs web arbitraris."</string>
<string name="save_password_message" msgid="767344687139195790">"Voleu que el navegador recordi aquesta contrasenya?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Xarxa Wi-fi oberta disponible"</item>
<item quantity="other" msgid="7915895323644292768">"Xarxes Wi-fi obertes disponibles"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Insereix un caràcter"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicació desconeguda"</string>
<string name="sms_control_title" msgid="7296612781128917719">"S\'estan enviant missatges SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connectat com a dispositiu multimèdia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connectat com a càmera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connectat com a instal·lador"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Toca per obtenir altres opcions d\'USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Empremta SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Empremta SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra-ho tot"</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Selecció d\'activitat"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Ús compartit amb..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 944eb2f..c074e7b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Umožňuje aplikacím sledovat, které klávesy používáte, a to i při práci s jinými aplikacemi (například při zadávání hesla). Běžné aplikace by toto nastavení nikdy neměly vyžadovat."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vazba k metodě zadávání dat"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Umožňuje držiteli vázat se na nejvyšší úroveň rozhraní pro zadávání dat. Běžné aplikace by toto nastavení nikdy neměly využívat."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"vazba na tapetu"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní tapety. Běžné aplikace by toto oprávnění nikdy neměly potřebovat."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"PSČ"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Stát"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"PSČ"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Okres"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ostrov"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Okres"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Department"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Farnost"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Oblast"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirát"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čtení historie a záložek Prohlížeče"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikaci číst všechny navštívené adresy URL a záložky Prohlížeče."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zápis do historie a záložek Prohlížeče"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umožní aplikaci změnit historii či záložky prohlížeče uložené v telefonu. Škodlivé aplikace mohou pomocí tohoto nastavení vymazat či pozměnit data Prohlížeče."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"nastavit budík v budíku"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Dovoluje aplikaci nastavit budík v nainstalované aplikaci budíku. Některé budíkové aplikace nemusí tuto funkci implementovat."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikaci změnit oprávnění prohlížeče poskytovat informace o zeměpisné poloze. Škodlivé aplikace mohou toto nastavení použít k odesílání informací o umístění na libovolné webové stránky."</string>
<string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"K dispozici je veřejná síť WiFi"</item>
<item quantity="other" msgid="7915895323644292768">"Jsou k dispozici veřejné sítě WiFi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Vkládání znaků"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznámá aplikace"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Odesílání zpráv SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Připojeno jako mediální zařízení"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Připojeno jako fotoaparát"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Připojeno jako instalátor"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Dotykem zobrazíte další možnosti USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Digitální otisk SHA-256"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Digitální otisk SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Zobrazit vše..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Vybrat činnost"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Sdílet..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c573322..0038b29 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -262,6 +262,10 @@
<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 applikationer."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<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 applikationer."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Stat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Amt"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ø"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Afdeling"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Præfektur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Sogn"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"læs browserens oversigt og 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>
@@ -732,6 +724,10 @@
<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 applikationen angiver en alarm i et installeret alarmprogram. Nogle alarmprogrammer kan ikke implementere denne funktion."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Skift browsertilladelser for geografisk placering"</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>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Åbent Wi-Fi-netværk tilgængeligt"</item>
<item quantity="other" msgid="7915895323644292768">"Der er åbne Wi-Fi-netværk tilgængelige"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Indsæt tegn"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukendt applikation"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sender sms-beskeder"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilsluttet som en medieenhed"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilsluttet som et kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilsluttet som et installationsprogram"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Tryk for at se andre valgmuligheder for USB-tilslutning"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeraftryk:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeraftryk:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Se alle..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Vælg aktivitet"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Del med..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 723d0a9..508b65d 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -262,6 +262,10 @@
<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>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Anwendungen benötigt werden."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"An einen Hintergrund binden"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Anwendungen benötigt werden."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provinz"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postleitzahl"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Bundesstaat/-land"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postleitzahl"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Landkreis"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Insel"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Bezirk"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Distrikt"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Präfektur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Gemeinde"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Gebiet"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Browserverlauf und Lesezeichen 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>
@@ -732,6 +724,10 @@
<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>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolokalisierungsberechtigungen des Browsers ändern"</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>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Verfügbares WLAN-Netzwerk öffnen"</item>
<item quantity="other" msgid="7915895323644292768">"Verfügbare WLAN-Netzwerke öffnen"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Zeichen einfügen"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Unbekannte Anwendung"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Kurznachrichten werden gesendet"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Als Mediengerät angeschlossen"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Als Kamera angeschlossen"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Als Installationsprogramm angeschlossen"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Zum Anzeigen weiterer USB-Optionen tippen"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 22a74b9..1bf806a 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Επιτρέπει σε εφαρμογές να παρακολουθούν τα πλήκτρα που πατάτε, ακόμη και σε μια άλλη εφαρμογή (όπως π.χ. η καταχώρηση ενός κωδικού πρόσβασης). Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"δέσμευση σε μέθοδο εισόδου"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας μεθόδου εισόδου. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"δέσμευση σε ταπετσαρία"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας ταπετσαρίας. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Επαρχία"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Ταχυδρομικός κώδικας"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Πολιτεία"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Ταχυδρομικός κώδικας"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Κομητεία"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Νησί"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Περιφέρεια"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Τμήμα"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Νομός"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Ενορία"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Περιοχή"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Εμιράτο"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ανάγνωση ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Επιτρέπει στην εφαρμογή την ανάγνωση όλων των διευθύνσεων URL που το πρόγραμμα περιήγησης έχει επισκεφθεί και όλων των σελιδοδεικτών του προγράμματος περιήγησης."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"εγγραφή ιστορικού και σελιδοδεικτών προγράμματος περιήγησης"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Επιτρέπει σε μια εφαρμογή να τροποποιήσει το ιστορικό ή τους σελιδοδείκτες του προγράμματος περιήγησης που βρίσκονται αποθηκευμένα στο τηλέφωνό σας. Κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να διαγράψουν ή να τροποποιήσουν τα δεδομένα του προγράμματος περιήγησης."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"ρύθμιση ειδοποίησης σε ξυπνητήρι"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Επιτρέπει στην εφαρμογή να ρυθμίσει μια ειδοποίηση σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Κάποιες εφαρμογές ξυπνητηριού ενδέχεται να μην περιλαμβάνουν αυτή τη λειτουργία."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Τροποποίηση δικαιωμάτων γεωγραφικής θέσης προγράμματος περιήγησης"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Επιτρέπει σε μια εφαρμογή την τροποποίηση των δικαιωμάτων γεωγραφικής θέσης του προγράμματος περιήγησης. Οι κακόβουλες εφαρμογές μπορούν να το χρησιμοποιήσουν για να επιτρέψουν την αποστολή στοιχείων τοποθεσίας σε αυθαίρετους ιστότοπους."</string>
<string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi"</item>
<item quantity="other" msgid="7915895323644292768">"Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Εισαγωγή χαρακτήρα"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Άγνωστη εφαρμογή"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Αποστολή μηνυμάτων SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Συνδεδεμένο ως συσκευή πολυμέσων"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Συνδεδεμένο ως φωτογραφική μηχανή"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Συνδεδεμένο ως πρόγραμμα εγκατάστασης"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Αγγίξτε για άλλες επιλογές USB"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Διαγρ. απ. χώρου USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Διαμόρφωση κάρτας SD"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2bf09f6..a22fafc 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"bind to an input method"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"set alarm in alarm clock"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modify Browser geo-location permissions"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Allows an application to modify the browser\'s geo-location permissions. Malicious applications can use this to allow the sending of location information to arbitrary websites."</string>
<string name="save_password_message" msgid="767344687139195790">"Do you want the browser to remember this password?"</string>
@@ -872,12 +880,9 @@
<string name="launch_warning_title" msgid="8323761616052121936">"Application redirected"</string>
<string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> is now running."</string>
<string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> was originally launched."</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 />
+ <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scale"</string>
+ <string name="screen_compat_mode_show" msgid="4013878876486655892">"Always show"</string>
+ <string name="screen_compat_mode_hint" msgid="2953716574198046484">"Reenable this with Settings > Applications > Manage applications."</string>
<string name="smv_application" msgid="295583804361236288">"The application <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced StrictMode policy."</string>
<string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
@@ -911,24 +916,34 @@
<item quantity="one" msgid="1634101450343277345">"Open available Wi-Fi network"</item>
<item quantity="other" msgid="7915895323644292768">"Open Wi-Fi networks available"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Insert character"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Unknown application"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sending SMS messages"</string>
<string name="sms_control_message" msgid="1289331457999236205">"A large number of SMS messages are being sent. Select \"OK\" to continue or \"Cancel\" to stop sending."</string>
<string name="sms_control_yes" msgid="2532062172402615953">"OK"</string>
<string name="sms_control_no" msgid="1715320703137199869">"Cancel"</string>
- <!-- no translation found for sim_removed_title (6227712319223226185) -->
- <skip />
- <!-- no translation found for sim_removed_message (2064255102770489459) -->
- <skip />
- <!-- no translation found for sim_done_button (827949989369963775) -->
- <skip />
- <!-- no translation found for sim_added_title (3719670512889674693) -->
- <skip />
- <!-- no translation found for sim_added_message (1209265974048554242) -->
- <skip />
- <!-- no translation found for sim_restart_button (4722407842815232347) -->
- <skip />
+ <string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
+ <string name="sim_removed_message" msgid="2064255102770489459">"The mobile network will be unavailable until you replace the SIM card."</string>
+ <string name="sim_done_button" msgid="827949989369963775">"Done"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
+ <string name="sim_added_message" msgid="1209265974048554242">"You must restart your device to access the mobile network."</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
<string name="date_time_set" msgid="5777075614321087758">"Set"</string>
@@ -959,6 +974,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connected as a media device"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connected as a camera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connected as an installer"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Touch for other USB options"</string>
<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>
@@ -1106,8 +1123,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 fingerprint"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 fingerprint"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"See all..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Select activity"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Share with..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ea642c9..7c61d39 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Admite que las aplicaciones observen las teclas que presionas, incluso al interactuar con otra aplicación (como el ingreso de una contraseña). Se debe evitar utilizarlo en aplicaciones normales."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a un método de entrada"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite al propietario vincularse a la interfaz de nivel superior de un método de entrada. Se debe evitar utilizarlo en aplicaciones normales."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un fondo de pantalla"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Se debe evitar utilizarlo en aplicaciones normales."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Condado"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Isla"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Circunscripción"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirato"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"leer historial y marcadores del navegador"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los marcadores del navegador."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escribir historial y marcadores del navegador"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite a una aplicación modificar el historial y los marcadores del navegador almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"configurar alarma en reloj alarma"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que la aplicación configure una alarma en una aplicación instalada de reloj alarma. Es posible que algunas aplicaciones de reloj alarma no implementen esta función."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizarlos para permitir el envío de información sobre la ubicación a sitos web de forma arbitraria."</string>
<string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Abrir red disponible de Wi-Fi"</item>
<item quantity="other" msgid="7915895323644292768">"Abrir redes disponibles de Wi-Fi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Insertar caracteres"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicación desconocida"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como un instalador"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Toca para otras opciones de USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleccionar actividad"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 44e1c94..1179764 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permite que las aplicaciones observen las teclas que pulsas incluso cuando interactúas con otra aplicación (como, por ejemplo, al introducir una contraseña). No debería ser necesario nunca para las aplicaciones normales."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"enlazar con un método de introducción de texto"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite enlazar con la interfaz de nivel superior de un método de introducción de texto. No debe ser necesario para las aplicaciones normales."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"enlazar con un fondo de pantalla"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite enlazar con la interfaz de nivel superior de un fondo de pantalla. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string>
@@ -519,7 +523,7 @@
<item msgid="7897544654242874543">"Trabajo"</item>
<item msgid="1103601433382158155">"Fax del trabajo"</item>
<item msgid="1735177144948329370">"Fax de casa"</item>
- <item msgid="603878674477207394">"Buscapersonas"</item>
+ <item msgid="603878674477207394">"Busca"</item>
<item msgid="1650824275177931637">"Otro"</item>
<item msgid="9192514806975898961">"Personalizar"</item>
</string-array>
@@ -562,7 +566,7 @@
<string name="phoneTypeWork" msgid="8863939667059911633">"Trabajo"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Fax del trabajo"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Fax de casa"</string>
- <string name="phoneTypePager" msgid="7582359955394921732">"Buscapersonas"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"Busca"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Otro"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Devolución de llamada"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Coche"</string>
@@ -574,7 +578,7 @@
<string name="phoneTypeTelex" msgid="3367879952476250512">"Télex"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Móvil del trabajo"</string>
- <string name="phoneTypeWorkPager" msgid="649938731231157056">"Buscapersonas del trabajo"</string>
+ <string name="phoneTypeWorkPager" msgid="649938731231157056">"Busca del trabajo"</string>
<string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistente"</string>
<string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
<string name="eventTypeCustom" msgid="7837586198458073404">"Personalizados"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que una aplicación modifique la información de los marcadores o del historial del navegador almacenada en el teléfono. Las aplicaciones malintencionadas pueden utilizar este permiso para borrar o modificar los datos del navegador."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"establecer alarma en un reloj"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite a la aplicación establecer una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar los permisos de ubicación geográfica del navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que una aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones malintencionadas pueden utilizar este permiso para permitir el envío de información sobre la ubicación a sitios web arbitrarios."</string>
<string name="save_password_message" msgid="767344687139195790">"¿Deseas que el navegador recuerde esta contraseña?"</string>
@@ -911,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Red Wi-Fi abierta disponible"</item>
<item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abiertas disponibles"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Insertar carácter"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicación desconocida"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensajes SMS..."</string>
@@ -959,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como un dispositivo de medios"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como una cámara"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectado como instalador"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Tocar para acceder a otras opciones de USB"</string>
<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>
@@ -1106,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Huella digital SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Huella digital SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver todas..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleccionar actividad"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Compartir con..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 14943a1..35fc0b9 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"به برنامه های کاربردی اجازه می دهد حتی زمانی که با برنامه دیگری در حال ارتباط هستید (مانند وارد کردن یک رمز ورود)، بتوانند کلیدهایی را که فشار می دهید ببینند. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"پیوند شده به روش ورودی"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"به نگهدارنده اجازه می دهد به رابط سطح بالای یک روش ورودی متصل شود. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"پیوند شده به تصویر زمینه"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"به نگهدارنده اجازه می دهد که به رابط سطح بالای تصویر زمینه متصل شود. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"استان"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"کد پستی"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"ایالت"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"کد پستی"</string>
+ <string name="autofill_county" msgid="237073771020362891">"بخش"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"جزیره"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"حوزه"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"اداره"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"حوزه اداری"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"ناحیه"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"منطقه"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"امارات"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"خواندن سابقه و نشانک های مرورگر"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"به برنامه کاربردی اجازه می دهد تا تمام URL های بازدید شده توسط مرورگر و تمام نشانک های آن را بخواند."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"نوشتن سابقه مرورگر و نشانک ها"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"به یک برنامه کاربردی اجازه می دهد سابقه مرورگر یا نشانک ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر داده های مرورگر شما استفاده کنند."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"تنظیم هشدار در ساعت زنگ دار"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"به برنامه کاربردی برای تنظیم یک هشدار در یک برنامه ساعت زنگ دار نصب شده اجازه می دهد. در برخی از برنامه های ساعت زنگ دار ممکن است این ویژگی اجرا نشود."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"اصلاح کردن مجوزهای مکان جغرافیایی مرورگر"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"به یک برنامه کاربردی اجازه می دهد مجوزهای مکان جغرافیایی مرورگر را تغییر دهد. برنامه های مضر می توانند از این گزینه استفاده کرده و اطلاعات مربوط به مکان را به وب سایت های غیر قانونی ارسال کنند."</string>
<string name="save_password_message" msgid="767344687139195790">"می خواهید مرورگر این رمز ورود را به خاطر داشته باشد؟"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"شبکه Wi-Fi موجود را باز کنید"</item>
<item quantity="other" msgid="7915895323644292768">"شبکه های Wi-Fi موجود را باز کنید"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"برنامه ناشناس"</string>
<string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"متصل شده به عنوان دستگاه رسانه ای"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"متصل شده به عنوان دوربین"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"متصل شده به عنوان نصب کننده"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"برای سایر گزینه های USB لمس کنید"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string>
@@ -1085,7 +1099,7 @@
<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_undo_deletes" msgid="8610996708225006328">"لغو موارد حذف شده."</string>
<string name="sync_do_nothing" msgid="8717589462945226869">"اکنون هیچ کاری انجام نشود."</string>
<string name="choose_account_label" msgid="4191313562041125787">"انتخاب یک حساب"</string>
<string name="number_picker_increment_button" msgid="4830170763103463443">"افزایش"</string>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"اثر انگشت SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"اثر انگشت SHA-1"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"مشاهده همه..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"انتخاب فعالیت"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"اشتراک گذاری با..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index fcae45c..2e3f921 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Antaa sovelluksien tarkkailla painamiasi näppäimiä jopa toisten sovellusten käytön yhteydessä (kuten salasanoja syötettäessä). Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"sitoudu syöttötapaan"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Antaa sovelluksen sitoutua syöttötavan ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Antaa sovelluksen sitoutua taustakuvan ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provinssi"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postinumero"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Osavaltio"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postinumero"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Lääni"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Saari"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Piiri"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Osasto"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektuuri"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Kunta"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Alue"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emiraatti"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lue selaimen historiaa ja kirjanmerkkejä"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Antaa sovelluksen lukea kaikki selaimen käyttämät URL-osoitteet ja selaimen kirjanmerkit."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"kirjoita selaimen historiaa ja kirjanmerkkejä"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Antaa sovelluksen muokata puhelimeen tallennettuja selaimen historia- ja kirjanmerkkitietoja. Haitalliset sovellukset voivat käyttää tätä pyyhkiäkseen tai muokatakseen selaimen tietoja."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"aseta herätys herätyskelloon"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Antaa sovelluksen asettaa herätyksen asennettuun herätyskellosovellukseen. Kaikki herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"muokkaa selaimen maantieteellisen sijainnin lupia"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Antaa sovelluksen muokata selaimen maantieteellisen sijainnin lupia. Haitalliset sovellukset saattavat käyttää tätä sijaintitietojen lähettämiseen satunnaisiin verkkosivustoihin."</string>
<string name="save_password_message" msgid="767344687139195790">"Haluatko selaimen muistavan tämän salasanan?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Avoin wifi-verkko käytettävissä"</item>
<item quantity="other" msgid="7915895323644292768">"Avoimia wifi-verkkoja käytettävissä"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Lisää merkki"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Tuntematon sovellus"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Tekstiviestien lähettäminen"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Kytketty medialaitteena"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kytketty kamerana"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Kytketty asennusohjelmana"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Käytä muita USB-vaihtoehtoja koskettamalla"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index be75a7e..a10b203 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permet à des applications d\'identifier les touches sur lesquelles vous appuyez même lorsque vous utilisez une autre application (lors de la saisie d\'un mot de passe, par exemple). Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"Association à un mode de saisie"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permet au support de se connecter à l\'interface de plus haut niveau d\'un mode de saisie. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"Se fixer sur un fond d\'écran"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permet au support de se fixer sur l\'interface de plus haut niveau d\'un fond d\'écran. Les applications normales ne devraient jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Province"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Code postal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"État"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Code postal"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Comté"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Île"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Département"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Préfecture"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Commune"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Région"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Émirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lire l\'historique et les favoris du navigateur"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Autorise l\'application à lire toutes les URL auxquelles le navigateur a accédé et tous ses favoris."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"écrire dans l\'historique et les favoris du navigateur"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet à une application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Des applications malveillantes peuvent exploiter cette fonction pour effacer ou modifier les données de votre navigateur."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"régler le réveil"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet à l\'application de définir une alarme dans un utilitaire faisant office de réveil. Certains réveils risquent ne pas prendre en charge cette fonctionnalité."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifier les autorisations de géolocalisation du navigateur"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet à une application de modifier les autorisations de géolocalisation du navigateur. Les applications malveillantes peuvent se servir de cette fonctionnalité pour envoyer des informations de lieu à des sites Web arbitraires."</string>
<string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Réseau Wi-Fi ouvert disponible"</item>
<item quantity="other" msgid="7915895323644292768">"Réseaux Wi-Fi ouverts disponibles"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Insérer un caractère"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Application inconnue"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Envoi de messages SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'appareil multimédia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Appuyez pour accéder aux autres options USB."</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index cf119d5..72ea506 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Aplikacijama omogućuje praćenje pritisnutih tipki kod interakcije s drugom aplikacijom (primjerice kod unosa zaporke). Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vezano uz način unosa"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Nositelju omogućuje da se veže uz sučelje najviše razine za metodu unosa. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezano s pozadinskom slikom"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Nositelju omogućuje da se veže uz sučelje najviše razine za pozadinsku sliku. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Pokrajina"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Poštanski broj"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Država"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Poštanski broj"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Županija"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Otok"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Okrug"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Odjel"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Župa"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Područje"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čitanje povijesti i oznaka preglednika"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Aplikaciji omogućuje čitanje svih URL-ova koje je preglednik posjetio i svih oznaka iz preglednika."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje povijesti i oznaka preglednika"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Aplikaciji omogućuje izmjenu povijesti ili oznaka preglednika koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu podataka o pregledniku."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"namjesti alarm na budilici"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Omogućuje aplikaciji da namjesti alarm u instaliranoj aplikaciji budilice. Neke aplikacije budilice možda neće primijeniti ovu značajku."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Izmijeni dopuštenja za geo-lociranje u pregledniku"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Aplikaciji omogućuje izmjenu dopuštenja za geolokaciju u pregledniku. Zlonamjerne aplikacije to mogu koristiti za omogućavanje slanja informacija o lokaciji na proizvoljne web-lokacije."</string>
<string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu zaporku?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Omogućavanje otvaranja Wi-Fi mreže"</item>
<item quantity="other" msgid="7915895323644292768">"Omogućavanje otvaranja Wi-Fi mreža"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Umetni znak"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Nepoznata aplikacija"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Slanje SMS poruka"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Spojen kao medijski uređaj"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Spojen kao fotoaparat"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Spojen kao instalacijski program"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Dodirnite za ostale opcije USB-a"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 5fc1c31..3a5fd40 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Lehetővé teszi az alkalmazások számára, hogy figyeljék a lenyomott billentyűket még másik alkalmazás használata esetén is (például jelszó beírásakor). A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"összekapcsolás egy beviteli módszerrel"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Lehetővé teszi a használó számára a beviteli módszer legfelső szintű kezelőfelületéhez való csatlakozást. A normál alkalmazások soha nem használják ezt."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"összekapcsolás háttérképpel"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Lehetővé teszi a használó számára, hogy csatlakozzon egy háttérkép legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt böngészési előzményeket és könyvjelzőket. A rosszindulatú alkalmazások felhasználhatják ezt a böngésző adatainak törlésére vagy módosítására."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"ébresztő beállítása az ébresztőórában"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Lehetővé teszi az alkalmazások számára, hogy beállítsanak egy ébresztőt egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"A böngésző helymeghatározási engedélyeinek módosítása"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a böngésző helymeghatározási engedélyeit. A rosszindulatú alkalmazások kihasználhatják ezt arra, hogy helyadatokat küldjenek tetszőleges webhelyeknek."</string>
<string name="save_password_message" msgid="767344687139195790">"Szeretné, hogy a böngésző megjegyezze a jelszót?"</string>
@@ -911,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Nyílt Wi-Fi hálózat elérhető"</item>
<item quantity="other" msgid="7915895323644292768">"Nyílt Wi-Fi hálózatok elérhetők"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Karakter beszúrása"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Ismeretlen alkalmazás"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS-ek küldése"</string>
@@ -959,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Csatlakoztatva médiaeszközként"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Csatlakoztatva kameraként"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Csatlakoztatva telepítőként"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Érintse meg a további USB-opciókért"</string>
<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>
@@ -1106,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 ujjlenyomat:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 ujjlenyomat:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Összes megtekintése..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Tevékenység kiválasztása"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Megosztás..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index fa7fefb..85b8012 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Mengizinkan aplikasi melihat tombol yang Anda tekan bahkan ketika berinteraksi dengan aplikasi lain (seperti memasukkan sandi). Tidak pernah diperlukan untuk aplikasi normal."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"mengikat ke metode masukan"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi pada suatu metode masukan. Tidak diperlukan untuk aplikasi normal."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"mengikat ke wallpaper"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu wallpaper. Tidak diperlukan untuk aplikasi normal."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provinsi"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Kode pos"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Negara Bagian"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Kode pos"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Wilayah"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Pulau"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrik"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departemen"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Kampung"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Area"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Peramban"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Izinkan aplikasi membaca semua URL yang telah dikunjungi Peramban, dam semua bookmark Peramban."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Peramban"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Mengizinkan aplikasi mengubah riwayat atau bookmark Peramban yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data Peramban."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"setel alarm di jam alarm"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Perbolehkan aplikasi untuk menyetel alarm di aplikasi jam alarm yang terpasang. Beberapa aplikasi jam alarm tidak dapat menerapkan fitur ini."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ubah izin geolokasi Peramban"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Mengizinkan aplikasi mengubah izin geolokasi Peramban. Aplikasi hasad dapat menggunakan ini untuk mengizinkan pengiriman informasi lokasi ke situs web sembarangan."</string>
<string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Jaringan Wi-Fi terbuka tersedia"</item>
<item quantity="other" msgid="7915895323644292768">"Jaringan Wi-Fi terbuka tersedia"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Sisipkan huruf"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplikasi tidak dikenal"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Mengirim pesan SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Terhubung sebagai perangkat media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Terhubung sebagai kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Terhubung sebagai pemasang"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk opsi USB lainnya"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6e19cb5..147cb70 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Consente il rilevamento da parte delle applicazioni dei tasti premuti anche durante l\'interazione con un\'altra applicazione (come nel caso di inserimento di una password). Non dovrebbe essere mai necessario per le normali applicazioni."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"associaz. a un metodo di inserimento"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Consente l\'associazione all\'interfaccia principale di un metodo di inserimento. Non dovrebbe essere mai necessario per le normali applicazioni."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"associazione a sfondo"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Consente l\'associazione di uno sfondo all\'interfaccia principale. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Consente a un\'applicazione di modificare la cronologia o i segnalibri del browser memorizzati sul telefono. Le applicazioni dannose possono sfruttare questa possibilità per cancellare o modificare i dati del browser."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"impostazione allarmi nella sveglia"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. Alcune applicazioni sveglia potrebbero non supportare questa funzione."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica le autorizzazioni di localizzazione geografica del browser"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Consente a un\'applicazione di modificare le autorizzazioni di localizzazione geografica del browser. Le applicazioni dannose possono utilizzare questa autorizzazione per consentire l\'invio di informazioni sulla posizione a siti web arbitrari."</string>
<string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
@@ -911,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Rete Wi-Fi aperta disponibile"</item>
<item quantity="other" msgid="7915895323644292768">"Reti Wi-Fi aperte disponibili"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Inserisci carattere"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Applicazione sconosciuta"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Invio SMS"</string>
@@ -959,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Collegato come dispositivo multimediale"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Collegato come fotocamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Collegato come installer"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Tocca per altre opzioni USB"</string>
<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>
@@ -1106,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Fingerprint SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Fingerprint SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Mostra tutto..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Seleziona attività"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Condividi con..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9c8b81d..159af64 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"מאפשר ליישומים לצפות במקשים שעליהם אתה לוחץ בעת אינטראקציה עם יישום אחר (כגון הזנת סיסמה). לא אמור להיות דרוש לעולם ליישום רגילים."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"הכפפה לשיטת קלט"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"מאפשר למחזיק להכפיף לממשק ברמה עליונה של שיטת קלט. לא אמור להידרש לעולם ביישומים רגילים."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"קשור לטפט"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"מאפשר למחזיק לקשור לממשק ברמה עליונה של טפט. לא אמור להידרש לעולם ביישומים רגילים."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"הכפפה לשירות Widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"פרובינציה"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"מיקוד"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"מדינה"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"מיקוד"</string>
+ <string name="autofill_county" msgid="237073771020362891">"מחוז"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"אי"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"רובע"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"מחלקה"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"תחום שיפוט"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"קהילה"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"אזור"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"אמירות"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"קרא היסטוריה וסימניות של דפדפן"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"מאפשר ליישום לקרוא את כל כתובות האתרים שבהן ביקר הדפדפן, ואת כל הסימניות של הדפדפן."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתיבת היסטוריה וסימניות של דפדפן"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר התראה בשעון המעורר"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"מאפשר ליישום להגדיר התראה ביישום מותקן של שעון מעורר. חלק מיישומי השעון המעורר עשויים שלא ליישם תכונה זו."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"שנה את ההרשאות של מיקום גיאוגרפי בדפדפן"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"מאפשר ליישום לשנות את הרשאות היעד הגיאוגרפי של הדפדפן. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לאפשר שליחה של פרטי מיקום לאתרי אינטרנט אקראיים."</string>
<string name="save_password_message" msgid="767344687139195790">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"רשת Wi-Fi פתוחה זמינה"</item>
<item quantity="other" msgid="7915895323644292768">"רשתות Wi-Fi פתוחות זמינות"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"הוסף תו"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"יישום לא ידוע"</string>
<string name="sms_control_title" msgid="7296612781128917719">"שולח הודעות SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"מחובר כמכשיר מדיה"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"מחובר כמצלמה"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"מחובר כמתקין"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"גע לקבלת אפשרויות USB נוספות"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7614dd1..c2b6dd2 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"別のアプリケーションへの入力(パスワードなど)でもキー入力を監視することをアプリケーションに許可します。通常のアプリケーションではまったく必要ありません。"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"入力方法に関連付ける"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"入力方法のトップレベルインターフェースに関連付けることを所有者に許可します。通常のアプリケーションにはまったく必要ありません。"</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"壁紙にバインド"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"壁紙のトップレベルインターフェースへのバインドを所有者に許可します。通常のアプリケーションでは不要です。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string>
@@ -701,30 +705,18 @@
<string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
<string name="autofill_address_summary_separator" msgid="7483307893170324129">"、 "</string>
<string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"地方"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"郵便番号"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"州"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"郵便番号"</string>
+ <string name="autofill_county" msgid="237073771020362891">"郡"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"島"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"地区"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"県"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"都道府県"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"行政区"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"地域"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"首長国"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ブラウザの履歴とブックマークを読み取る"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"ブラウザでアクセスしたすべてのURLおよびブラウザのすべてのブックマークの読み取りをアプリケーションに許可します。"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"ブラウザの履歴とブックマークを書き込む"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"携帯電話に保存されているブラウザの履歴やブックマークの修正をアプリケーショに許可します。これにより悪意のあるアプリケーションが、ブラウザのデータを消去または変更する恐れがあります。"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"アラームの設定"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"インストール済みアラームアプリケーションのアラーム設定をアプリケーションに許可します。この機能が実装されていないアラームアプリケーションもあります。"</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"ブラウザの位置情報へのアクセス権を変更"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"ブラウザの位置情報に対するアクセス権の変更をアプリケーションに許可します。この設定では、悪意のあるアプリケーションが任意のウェブサイトに位置情報を送信する可能性があります。"</string>
<string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Wi-Fiオープンネットワークが利用できます"</item>
<item quantity="other" msgid="7915895323644292768">"Wi-Fiオープンネットワークが利用できます"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"文字を挿入"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"不明なアプリケーション"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMSメッセージの送信中"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"メディアデバイスとして接続"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"カメラとして接続"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"インストーラとして接続"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"他のUSBオプションをタップしてください"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USBストレージのフォーマット"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SDカードをフォーマット"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b47d090..0c4c4b8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"애플리케이션이 다른 애플리케이션과 상호작용할 때에도 사용자가 누르는 키(예: 비밀번호 입력)를 볼 수 있도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"입력 방법 연결"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"권한을 가진 프로그램이 입력 방법에 대한 최상위 인터페이스를 사용하도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"배경화면 연결"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"권한을 가진 프로그램이 배경화면에 대한 최상위 인터페이스를 사용하도록 합니다. 일반 애플리케이션에는 절대로 필요하지 않습니다."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string>
@@ -701,30 +705,18 @@
<string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
<string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
<string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"도"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"우편번호"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"시/도"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"우편번호"</string>
+ <string name="autofill_county" msgid="237073771020362891">"구/군"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"섬"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"구"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"지역"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"현"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"군"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"구역"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"에미리트"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"브라우저의 기록 및 북마크 읽기"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"애플리케이션이 브라우저로 방문한 모든 URL과 브라우저의 모든 북마크를 읽도록 허용합니다."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"브라우저의 기록 및 북마크 쓰기"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"애플리케이션이 휴대전화에 저장된 브라우저 기록 또는 북마크를 수정할 수 있도록 허용합니다. 이 경우 악성 애플리케이션이 브라우저의 데이터를 지우거나 수정할 수 있습니다."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"알람 시계에 알람 설정"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"실치된 알람 시계 애플리케이션에 알람을 설정하도록 허용합니다. 일부 알람 시계 애플리케이션은 이 기능을 구현하지 않을 수 있습니다."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"브라우저 위치 정보 수정 권한"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"애플리케이션이 브라우저의 위치 정보 권한을 수정할 수 있도록 합니다. 악성 애플리케이션이 이를 사용하여 임의의 웹사이트에 위치 정보를 보낼 수도 있습니다."</string>
<string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"개방형 Wi-Fi 네트워크 사용 가능"</item>
<item quantity="other" msgid="7915895323644292768">"개방형 Wi-Fi 네트워크 사용 가능"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"문자 삽입"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"알 수 없는 애플리케이션"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS 메시지를 보내는 중"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"미디어 기기로 연결됨"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"카메라로 연결됨"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"설치 프로그램으로 연결됨"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"다른 USB 옵션을 보려면 터치하세요."</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB 저장소 포맷"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD 카드 포맷"</string>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 지문:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 지문:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"전체 보기..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"활동 선택"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"공유 대상..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 85130ba1..92d5a87 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -20,14 +20,14 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Resources for MultiWaveView in LockScreen -->
- <array name="ic_lockscreen_targets_when_silent">
+ <array name="lockscreen_targets_when_silent">
<item>@null</item>"
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
<item>@drawable/ic_lockscreen_soundon</item>
</array>
- <array name="ic_lockscreen_targets_when_soundon">
+ <array name="lockscreen_targets_when_soundon">
<item>@null</item>"
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 44d8dc6e..1e18e3c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Leidžia programoms žiūrėti jūsų paspaustus klavišus sąveikaujant su kita programa (pvz., įvedant slaptažodį). Neturėtų reikėti įprastoms programoms."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"susaistyti įvesties būdą"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Leidžia savininkui susisaistyti su įvesties būdo aukščiausio lygio sąsaja. Neturėtų reikėti įprastoms programoms."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"susaistyti su darbalaukio fonu"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Leidžia savininkui susisaistyti su aukščiausio lygio darbalaukio fono sąsaja. Neturėtų reikėti įprastose programose."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincija"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Pašto kodas"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Valstija"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Pašto kodas"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Apskritis"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Sala"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Rajonas"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departamentas"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektūra"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Parapija"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Sritis"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emyratas"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"skaityti naršyklės istoriją ir žymes"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Leidžia programai skaityti visus URL, kuriuose apsilankė naršyklė, ir visas naršyklės žymas."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rašyti naršyklės istoriją ir žymes"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Leidžia programai keisti naršyklės istoriją ar žymes, išsaugotus jūsų telefone. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų naršyklės duomenis."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"nustatyti žadintuvo signalą"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose šios funkcijos gali nebūti."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Keisti naršyklės geografinės vietovės leidimus"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Leidžia programai keisti geografinių naršyklės vietų leidimus. Kenkėjiškos programos tai gali naudoti siunčiant vietos informaciją atsitiktinėms svetainėms."</string>
<string name="save_password_message" msgid="767344687139195790">"Ar norite, kad naršyklė atsimintų šį slaptažodį?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Atidaryti galimą „Wi-Fi“ tinklą"</item>
<item quantity="other" msgid="7915895323644292768">"Atidaryti galimus „Wi-Fi“ tinklus"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Įterpti simbolį"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Nežinoma programa"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS pranešimų siuntimas"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Prij. kaip medijos įrenginys"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Prij. kaip fotoap."</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Prij. kaip diegimo programa"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Jei norite matyti kitas USB parinktis, palieskite"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 kontrolinis kodas"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 kontrolinis kodas"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Žr. viską..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Pasirinkti veiklą"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Bendrinti su..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index bc8b64c..43d640b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Ļauj lietojumprogrammām sekot līdzi nospiestajiem taustiņiem, mijiedarbojoties ar citu lietojumprogrammu (piemēram, ievadot paroli). Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"saistīt ar ievades metodi"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ļauj īpašniekam saistīt ar ievades metodes augšējā līmeņa saskarni. Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"saistīt ar tapeti"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ļauj īpašniekam saistīties ar tapetes augšējā līmeņa saskarni. Parastajās lietojumprogrammās nekad nav nepieciešama."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ļauj lietojumprogrammai pārveidot tālrunī saglabāto pārlūkprogrammas vēsturi un grāmatzīmes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu pārlūkprogrammas datus."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"iestatīt trauksmi modinātājpulkstenī"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Ļauj lietojumprogrammai iestatīt trauksmi instalētajā modinātājpulksteņa lietojumprogrammā. Dažās modinātājpulksteņu lietojumprogrammās šī funkcija var nebūt īstenojama."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ļauj lietojumprogrammai pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string>
<string name="save_password_message" msgid="767344687139195790">"Vai vēlaties, lai pārlūkprogrammā tiktu saglabāta šī parole?"</string>
@@ -911,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Ir pieejams atvērts Wi-Fi tīkls"</item>
<item quantity="other" msgid="7915895323644292768">"Ir pieejami atvērti Wi-Fi tīkli."</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Ievietojiet rakstzīmi"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Nezināma lietojumprogramma"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Īsziņu sūtīšana"</string>
@@ -959,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pievienots kā multivides ierīce"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pievienots kā kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pievienots kā instalēšanas programma"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Pieskarieties, lai skatītu citas USB opcijas."</string>
<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>
@@ -1106,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 identifikators"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 identifikators:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Skatīt visas"</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Darbību atlasīšana"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Kopīgot ar..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 2cf00e0..3921be9 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -46,8 +46,7 @@
<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="invalidPuk" msgid="8761456210898036513">"Taipkan PUK yang mempunyai 8 nombor atau lebih panjang."</string>
<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>
@@ -153,7 +152,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>
- <!-- outdated translation 5833510281787786290 --> <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"100+"</string>
+ <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</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>
@@ -192,10 +191,8 @@
<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_receiveEmergencyBroadcast" msgid="1803477660846288089">"terima siaran kecemasan"</string>
+ <string name="permdesc_receiveEmergencyBroadcast" msgid="7118393393716546131">"Membenarkan aplikasi menerima dan memproses mesej siaran kecemasan. Kebenaran ini hanya tersedia kepada aplikasi sistem."</string>
<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>
@@ -226,10 +223,8 @@
<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_retrieve_window_content" msgid="8022588608994589938">"dapatkan semula kandungan skrin"</string>
+ <string name="permdesc_retrieve_window_content" msgid="3390962289797156152">"Membenarkan aplikasi untuk mendapatkan kembali kandungan tetingkap aktif. Aplikasi berniat jahat boleh mendapatkan kembali kandungan keseluruhan tetingkap dan memeriksa semua teksnya kecuali kata laluan."</string>
<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>
@@ -250,10 +245,8 @@
<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>
<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) -->
- <skip />
+ <string name="permlab_confirm_full_backup" msgid="5557071325804469102">"sahkan penyandaran penuh atau pemulihan operasi"</string>
+ <string name="permdesc_confirm_full_backup" msgid="9005017754175897954">"Membenarkan aplikasi melancarkan UI pengesahan sandaran penuh. Bukan untuk digunakan oleh mana-mana aplikasi."</string>
<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>
@@ -269,6 +262,10 @@
<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_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <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>
@@ -277,10 +274,8 @@
<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) -->
- <skip />
- <!-- no translation found for permdesc_setPointerSpeed (137436038503379864) -->
- <skip />
+ <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"tukar kelajuan penuding"</string>
+ <string name="permdesc_setPointerSpeed" msgid="137436038503379864">"Membenarkan aplikasi menukar kelajuan penuding tetikus atau pad jejak pada bila-bila masa sahaja. Seharusnya tidak diperlukan untuk aplikasi biasa."</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"hantar isyarat Linux kepada aplikasi"</string>
<string name="permdesc_signalPersistentProcesses" msgid="3565530463215015289">"Membenarkan aplikasi meminta isyarat yang dibekalkan dihantar kepada semua proses gigih."</string>
<string name="permlab_persistentActivity" msgid="8659652042401085862">"buatkan aplikasi sentiasa berjalan"</string>
@@ -328,14 +323,10 @@
<string name="permlab_writeContacts" msgid="644616215860933284">"tulis data kenalan"</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>
- <!-- 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_readProfile" msgid="2211941946684590103">"baca data profil"</string>
+ <string name="permdesc_readProfile" product="default" msgid="4732942280141331352">"Membenarkan aplikasi membaca semua maklumat profil peribadi anda. Aplikasi berniat jahat boleh menggunakannya untuk mengenal pasti anda dan menghantar maklumat peribadi anda kepada orang lain."</string>
+ <string name="permlab_writeProfile" msgid="6561668046361989220">"menulis data profil"</string>
+ <string name="permdesc_writeProfile" product="default" msgid="8040643023682531996">"Membenarkan aplikasi mengubah suai maklumat profil peribadi anda. Aplikasi berniat jahat boleh menggunakan ini untuk memadamkan atau mengubah suai data profil anda."</string>
<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>
@@ -472,10 +463,8 @@
<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>
<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 (7093963230333602420) -->
- <skip />
+ <string name="permlab_vpn" msgid="8345800584532175312">"memintas dan mengubah suai semua trafik rangkaian"</string>
+ <string name="permdesc_vpn" msgid="7093963230333602420">"Membenarkan aplikasi memintas dan memeriksa semua trafik rangkaian untuk mewujudkan sambungan VPN. Aplikasi berniat jahat boleh memantau, menghalakan semula atau mengubah suai bingkisan rangkaian tanpa pengetahuan anda."</string>
<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>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"membaca tetapan penyegerakan"</string>
@@ -502,14 +491,10 @@
<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_readNetworkUsageHistory (6040738474779135653) -->
- <skip />
- <!-- no translation found for permlab_manageNetworkPolicy (2562053592339859990) -->
- <skip />
- <!-- no translation found for permdesc_manageNetworkPolicy (3723795285132803958) -->
- <skip />
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"baca sejarah penggunaan rangkaian"</string>
+ <string name="permdesc_readNetworkUsageHistory" msgid="6040738474779135653">"Membenarkan aplikasi membaca sejarah penggunaan rangkaian untuk rangkaian dan aplikasi khusus."</string>
+ <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"urus dasar rangkaian"</string>
+ <string name="permdesc_manageNetworkPolicy" msgid="3723795285132803958">"Membenarkan aplikasi mengurus dasar rangkaian dan menentukan peraturan khusus aplikasi."</string>
<!-- no translation found for permlab_modifyNetworkAccounting (5088217309088729650) -->
<skip />
<!-- no translation found for permdesc_modifyNetworkAccounting (8702285686629184404) -->
@@ -532,10 +517,8 @@
<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 policydesc_disableCamera (5680054212889413366) -->
- <skip />
+ <string name="policylab_disableCamera" msgid="6395301023152297826">"Lumpuhkan kamera"</string>
+ <string name="policydesc_disableCamera" msgid="5680054212889413366">"Menghalang penggunaan semua kamera peranti"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Laman Utama"</item>
<item msgid="869923650527136615">"Mudah alih"</item>
@@ -650,12 +633,9 @@
<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_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 />
+ <string name="keyguard_password_enter_puk_code" msgid="5965173481572346878">"Masukkan PUK dan kod PIN baru"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kod PUK"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="2987350144349051286">"Kod PIN Baru"</string>
<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>
@@ -680,10 +660,8 @@
<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 lockscreen_missing_sim_instructions_long (7138450788301444298) -->
- <skip />
- <!-- no translation found for lockscreen_permanent_disabled_sim_instructions (1631853574702335453) -->
- <skip />
+ <string name="lockscreen_missing_sim_instructions_long" msgid="7138450788301444298">"Kad SIM tiada atau tidak boleh dibaca. Sila masukkan kad SIM."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="1631853574702335453">"Kad SIM anda dilumpuhkan secara kekal."\n" Sila hubungi pembekal perkhidmatan wayarles anda untuk mendapatkan kad SIM lain."</string>
<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>
@@ -729,30 +707,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Wilayah"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Poskod"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Negeri"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Poskod"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Wilayah"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Pulau"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Daerah"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Jabatan"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Wilayah"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Kariah"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Kawasan"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emiriah"</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>
@@ -760,6 +726,10 @@
<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>
<string name="permlab_setAlarm" msgid="5924401328803615165">"menetapkan penggera pada 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>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<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>
@@ -951,6 +921,22 @@
<item quantity="one" msgid="1634101450343277345">"Rangkaian Wi-Fi terbuka tersedia"</item>
<item quantity="other" msgid="7915895323644292768">"Rangkaian Wi-Fi terbuka tersedia"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Masukkan aksara"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplikasi tidak dikenali"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Menghantar mesej SMS"</string>
@@ -999,6 +985,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Disambungkan sebagai peranti media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Disambungkan sebagai kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Disambungkan sebagai pemasang"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Sentuh untuk mendapatkan pilihan USB yang lain"</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>
@@ -1065,10 +1053,8 @@
<string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
<string name="vpn_title" msgid="8219003246858087489">"VPN diaktifkan."</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Ketik untuk mengurus rangkaian."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Bersambung kepada <xliff:g id="SESSION">%s</xliff:g>. Ketik untuk mengurus rangkaian."</string>
<string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
<string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
@@ -1120,32 +1106,19 @@
<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) -->
- <skip />
- <!-- no translation found for action_menu_overflow_description (2295659037509008453) -->
- <skip />
- <!-- no translation found for storage_internal (7556050805474115618) -->
- <skip />
- <!-- no translation found for storage_sd_card (8921771478629812343) -->
- <skip />
- <!-- no translation found for storage_usb (3017954059538517278) -->
- <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="action_bar_home_description" msgid="5293600496601490216">"Navigasi laman utama"</string>
+ <string name="action_bar_up_description" msgid="2237496562952152589">"Navigasi ke atas"</string>
+ <string name="action_menu_overflow_description" msgid="2295659037509008453">"Lagi pilihan"</string>
+ <string name="storage_internal" msgid="7556050805474115618">"Storan Dalaman"</string>
+ <string name="storage_sd_card" msgid="8921771478629812343">"Kad SD"</string>
+ <string name="storage_usb" msgid="3017954059538517278">"Storan USB"</string>
+ <string name="extract_edit_menu_button" msgid="302060189057163906">"Edit..."</string>
+ <string name="data_usage_warning_title" msgid="1955638862122232342">"Amaran penggunaan data"</string>
+ <string name="data_usage_warning_body" msgid="3354394590936526648">"penggunaan melebihi <xliff:g id="SIZE">%s</xliff:g>"</string>
+ <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"Data 2G-3G dilumpuhkan"</string>
+ <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"Data 4G dilumpuhkan"</string>
+ <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Data mudah alih dilumpuhkan"</string>
+ <string name="data_usage_limit_body" msgid="2182247539226163759">"ketik untuk mendayakan"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Sijil keselamatan"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Sijil ini sah."</string>
<string name="issued_to" msgid="454239480274921032">"Dikeluarkan kepada:"</string>
@@ -1156,17 +1129,15 @@
<string name="validity_period" msgid="8818886137545983110">"Kesahan:"</string>
<string name="issued_on" msgid="5895017404361397232">"Dikeluarkan pada:"</string>
<string name="expires_on" msgid="3676242949915959821">"Tamat tempoh pada:"</string>
- <!-- no translation found for serial_number (758814067660862493) -->
- <skip />
- <!-- no translation found for fingerprints (4516019619850763049) -->
- <skip />
- <!-- no translation found for sha256_fingerprint (4391271286477279263) -->
- <skip />
- <!-- no translation found for sha1_fingerprint (7930330235269404581) -->
- <skip />
+ <string name="serial_number" msgid="758814067660862493">"Nombor siri:"</string>
+ <string name="fingerprints" msgid="4516019619850763049">"Cap jari:"</string>
+ <string name="sha256_fingerprint" msgid="4391271286477279263">"Cap jari SHA-256:"</string>
+ <string name="sha1_fingerprint" msgid="7930330235269404581">"Cap jari SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Lihat semua..."</string>
<!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 67429b5..7db3f31 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Lar applikasjonen overvåke tastetrykk selv når interaksjonen er med et annet program (som å skrive inn et passord). Vanlige applikasjoner bør aldri trenge dette."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"binde til en inndatametode"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Lar applikasjonen binde til toppnivågrensesnittet for en inndatametode. Vanlige applikasjoner bør aldri trenge dette."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind til bakgrunnsbilde"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunnsbilder. Skal ikke være nødvendig for vanlige programmer."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind til modultjenste"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Delstat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Fylke"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Øy"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departement"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Sogn"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lese nettleserens logg og bokmerker"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lar applikasjonen lese alle adresser nettleseren har besøkt, og alle nettleserens bokmerker."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skrive til nettleserens logg og bokmerker"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Lar applikasjonen endre nettleserens logg og bokmerker lagret på telefonen. Ondsinnede applikasjoner kan bruke dette til å fjerne eller redigere nettleserens data."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"angi alarm i alarmklokke"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Lar programmet angi en alarm i et installert alarmklokkeprogram. Det kan hende at enkelte alarmklokkeprogrammer ikke implementerer denne funksjonen."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Endre nettleserens tillatelser for geografisk posisjonering"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillater programmet å endre nettleserens tillatelser for geografisk posisjonering. Skadelige programmer kan bruke denne funksjonen til å sende posisjonsopplysninger til vilkårlige nettsteder."</string>
<string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Åpent trådløsnett i nærheten"</item>
<item quantity="other" msgid="7915895323644292768">"Åpne trådløsnett i nærheten"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Sett inn tegn"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Ukjent applikasjon"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Sender SMS-meldinger"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Tilkoblet som medieenhet"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Tilkoblet som kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Tilkoblet som installasjonsprogram"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Berør for andre USB-alternativer"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index fe21bc8..52873e1 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Hiermee kan een app uw toetsaanslagen registreren, zelfs tijdens de interactie met een andere app (zoals de invoer van een wachtwoord). Nooit vereist voor normale apps."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"verbinden aan een invoermethode"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een invoermethode. Nooit vereist voor normale apps."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"verbinden met een achtergrond"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Hiermee staat u de houder toe zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postcode"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Staat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postcode"</string>
+ <string name="autofill_county" msgid="237073771020362891">"County"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Eiland"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departement"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectuur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Gemeente"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Gebied"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emiraat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"browsergeschiedenis en bladwijzers lezen"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Hiermee kan een app de URL\'s lezen die u via de browser heeft bezocht, evenals alle bladwijzers van de browser."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"browsergeschiedenis en bladwijzers schrijven"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Hiermee kan een app de op uw telefoon opgeslagen browsergeschiedenis of bladwijzers wijzigen. Schadelijke apps kunnen hiermee uw browsergegevens verwijderen of wijzigen."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"alarm instellen in wekker"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Geolocatierechten voor browser aanpassen"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Staat een app toe de geolocatierechten van de browser aan te passen. Schadelijke apps kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
<string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Open Wi-Fi-netwerk beschikbaar"</item>
<item quantity="other" msgid="7915895323644292768">"Open Wi-Fi-netwerken beschikbaar"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Onbekende app"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Gekoppeld als media-apparaat"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Gekoppeld als camera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Gekoppeld als installatieprogramma"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Raak aan voor andere USB-opties"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-vingerafdruk"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-vingerafdruk:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Alle bekijken..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Activiteit selecteren"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Delen met..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 60c9bdb..eedf51a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Pozwala aplikacjom na śledzenie naciskanych klawiszy, nawet podczas pracy z innym programem (na przykład podczas wpisywania hasła). Nigdy nie powinno być potrzebne normalnym aplikacjom."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"powiązanie ze sposobem wprowadzania tekstu"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Pozwala na powiązanie wybranego sposobu wprowadzania tekstu z interfejsem najwyższego poziomu. To uprawnienie nie powinno być nigdy wymagane przez zwykłe aplikacje."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"powiązanie z tapetą"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umożliwia posiadaczowi powiązać interfejs najwyższego poziomu dla tapety. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Województwo"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Kod pocztowy"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Stan"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Kod pocztowy"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Powiat"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Wyspa"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Dystrykt"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Gmina"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Obszar"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"odczyt historii i zakładek przeglądarki"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umożliwia aplikacji odczyt wszystkich adresów URL odwiedzonych przez przeglądarkę, a także wszystkich zakładek przeglądarki."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"zapis historii i zakładek przeglądarki"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umożliwia aplikacji modyfikowanie historii lub zakładek przeglądarki zapisanych w telefonie. Złośliwe aplikacje mogą używać tej opcji do usuwania lub modyfikowania danych przeglądarki."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"ustaw alarm w budziku"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Umożliwia aplikacji ustawienie alarmu w zainstalowanej aplikacji budzika. W niektórych aplikacjach budzika funkcja ta może nie być zaimplementowana."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Zezwala aplikacji na modyfikowanie uprawnień przeglądarki dotyczących lokalizacji geograficznej. Złośliwe aplikacje mogą używać tej opcji do wysyłania informacji o lokalizacji do dowolnych witryn internetowych."</string>
<string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
@@ -750,11 +746,11 @@
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Ponad 1 miesiąc temu"</string>
<plurals name="num_seconds_ago">
<item quantity="one" msgid="4869870056547896011">"sekundę temu"</item>
- <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sekund temu"</item>
+ <item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> sek. temu"</item>
</plurals>
<plurals name="num_minutes_ago">
<item quantity="one" msgid="3306787433088810191">"1 minutę temu"</item>
- <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> minut temu"</item>
+ <item quantity="other" msgid="2176942008915455116">"<xliff:g id="COUNT">%d</xliff:g> min. temu"</item>
</plurals>
<plurals name="num_hours_ago">
<item quantity="one" msgid="9150797944610821849">"godzinę temu"</item>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Otwórz dostępne sieci Wi-Fi"</item>
<item quantity="other" msgid="7915895323644292768">"Otwórz dostępne sieci Wi-Fi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Wstaw znak"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Nieznana aplikacja"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Wysyłanie wiadomości SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Podłączono jako urządzenie multimedialne."</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Podłączono jako aparat."</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Podłączono jako nośnik instalacyjny."</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Dotknij, aby wyświetlić inne opcje USB."</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Odcisk cyfrowy SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Odcisk cyfrowy SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Pokaż wszystkie"</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Wybierz czynność"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Udostępnij..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6af09f3..c89577d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permite às aplicações verificar as teclas que o utilizador prime, mesmo ao interagir com outras aplicações (como, por exemplo, ao introduzir uma palavra-passe). Nunca deve ser necessário para aplicações normais."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a um método de entrada"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite ao titular vincular a interface de nível superior a um método de entrada de som. Nunca deve ser necessário para aplicações normais."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a uma imagem de fundo"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite ao titular vincular a interface de nível superior de uma imagem de fundo. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Província"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Código postal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Código postal"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Concelho"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ilha"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Município"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Freguesia"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirado"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e marcadores do browser"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que a aplicação leia todos os URLs visitados pelo browser e todos os marcadores do browser."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e marcadores do browser"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que uma aplicação modifique o histórico e os marcadores do browser armazenados no telefone. As aplicações maliciosas podem utilizar esta permissão para apagar ou modificar os dados do browser."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificar permissões de localização geográfica do Navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite a uma aplicação modificar as permissões de localização geográfica do Navegador. As aplicações mal intencionadas podem utilizar isto para enviar informações de localização para Web sites arbitrários."</string>
<string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
<item quantity="other" msgid="7915895323644292768">"Abrir redes Wi-Fi disponíveis"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Introduzir carácter"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicação desconhecida"</string>
<string name="sms_control_title" msgid="7296612781128917719">"A enviar mensagens SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ligado como um aparelho multimédia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ligado como uma câmara"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ligado como um instalador"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Toque para outras opções USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Impressão digital SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Impressão digital SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Ver tudo..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Selecionar atividade"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Partilhar com..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d762274..1a7e0a8 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permite que os aplicativos vejam as teclas que você pressiona, mesmo quando estiver interagindo com outro aplicativo (como ao digitar uma senha). Aplicativos normais não devem precisar disso em momento algum."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"vincular a um método de entrada"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite que o detentor se sujeite à interface de nível superior de um método de entrada. Aplicativos normais não devem precisar disso em momento algum."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite que o detentor se sujeite à interface de nível superior de um plano de fundo. Aplicativos normais não devem precisar disso em momento algum."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Distrito"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Código Postal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"CEP"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Condado"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ilha"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departamento"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Município"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Paróquia"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Área"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirado"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"ler histórico e favoritos do Navegador"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite que o aplicativo leia todos os URLs visitados pelo Navegador e todos os favoritos do Navegador."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"gravar histórico e favoritos do Navegador"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite que um aplicativo modifique o histórico ou os favoritos do Navegador armazenados no seu telefone. Aplicativos maliciosos podem usar isso para apagar ou modificar os dados do seu Navegador."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"definir alarme no despertador"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite que o aplicativo defina um alarme em um aplicativo de despertador instalado. Talvez alguns aplicativos de despertador não implementem esse recurso."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifique as permissões de geolocalização do seu navegador"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite que um aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações de localização a sites arbitrários."</string>
<string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Rede Wi-Fi aberta disponível"</item>
<item quantity="other" msgid="7915895323644292768">"Redes Wi-Fi abertas disponíveis"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Inserir caractere"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicativo desconhecido"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Enviando mensagens SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como um dispositivo de mídia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectadas como uma câmera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectados como um instalador"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Toque para obter outras opções USB"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 5fd5d45..4f0e385 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -275,6 +275,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"\"Permetta ad ina applicaziun dad identifitgar las tastas che Vus smatgais, era durant l\'utilisaziun dad in auter program (durant l\'endataziun dad in pled-clav, per exempel). Applicaziuns normalas na duessan betg avair access a questa funcziun.\""</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"associar cun ina metoda d\'endataziun"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permetta da sa fixar al nivel d\'interfatscha pli aut dad ina metoda d\'endataziun. Betg previs per applicaziuns normalas."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sa fixar vid in fund davos"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permetta da sa fixar al nivel d\'interfatscha pli aut dad ina metoda d\'endataziun. Betg previs per applicaziuns normalas."</string>
<!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -814,6 +818,10 @@
<skip />
<!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
<skip />
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifitgar las autorisaziuns da geolocalisaziun dal navigatur"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permetta ad ina applicaziun da modifitgar las permissiuns da geolocalisaziun dal navigatur. Applicaziuns donnegiusas pon utilisar questa funcziun per trametter datas da posiziun a websites arbitraras."</string>
<string name="save_password_message" msgid="767344687139195790">"Vulais Vus ch\'il navigatur memorisescha quest pled-clav?"</string>
@@ -1010,6 +1018,22 @@
<item quantity="one" msgid="1634101450343277345">"Rait WLAN averta disponibla"</item>
<item quantity="other" msgid="7915895323644292768">"Raits WLAN avertas disponiblas"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Inserir in caracter"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Applicaziun nunenconuschenta"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Trametter messadis SMS"</string>
@@ -1063,6 +1087,8 @@
<skip />
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<!-- no translation found for usb_notification_message (4447869605109736382) -->
<skip />
<!-- outdated translation 8663247929551095854 --> <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatar la carta SD"</string>
@@ -1279,4 +1305,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ad3d64d..61a0d7b 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Permite unei aplicaţii să monitorizeze tastele pe care le apăsaţi când interacţionaţi cu o altă aplicaţie (cum ar fi introducerea unei parole). Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"conectare la o metodă de intrare"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Permite deţinătorului să se conecteze la interfaţa de nivel superior a unei metode de intrare. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincie"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Cod poştal"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Stat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Cod ZIP"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Judeţ"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Insulă"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"District"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departament"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefectură"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Cartier"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Zonă"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"citire istoric şi marcaje în browser"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite aplicaţiei să citească toate adresele URL vizitate din browser şi toate marcajele din acesta."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"citire istoric şi marcaje în browser"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite unei aplicaţii să modifice istoricul şi marcajele din browser, stocate pe telefonul dvs. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din browser."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"setare alarmă pentru ceasul cu alarmă"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas de alarmă instalată. Este posibil ca unele aplicaţii de ceas de alarmă să nu implementeze această funcţie."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificare permisiuni pentru locaţia geografică a browserului"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite unei aplicaţii să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri Web arbitrare."</string>
<string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Reţea Wi-Fi deschisă disponibilă"</item>
<item quantity="other" msgid="7915895323644292768">"Reţele Wi-Fi deschise disponibile"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Introduceţi caracterul"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Aplicaţie necunoscută"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Se trimit mesaje SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectat ca dispozitiv media"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectat ca aparat foto"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectat ca program de instalare"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Atingeţi pentru alte opţiuni USB"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0bc2f44..d2907ae 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Позволяет приложению распознавать нажатые пользователем клавиши даже при работе с другим приложением (например, при вводе пароля). Не требуется для обычных приложений."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"связывать с методом ввода"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Позволяет выполнять привязку к интерфейсу ввода верхнего уровня. Не требуется для обычных приложений."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"связать с фоновым рисунком"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Разрешает выполнять привязку к интерфейсу фонового рисунка верхнего уровня. Не требуется для обычных приложений."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"привязка к службе виджетов"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Провинция"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Почтовый индекс"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Штат"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Почтовый индекс"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Округ"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Остров"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Район"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Департамент"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Округ"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Область"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Эмират"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"считывать историю и закладки браузера"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешает приложению считывать все URL, посещенные браузером, и все его закладки."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"записывать историю и закладки браузера"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Разрешает приложению изменять историю и закладки браузера, сохраненные в вашем телефоне. Вредоносное ПО может пользоваться этим, чтобы стирать или изменять данные вашего браузера."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"настраивать сигнал будильника"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Позволяет настраивать сигнал установленного приложения будильника. Для некоторых приложений будильника эта функция может быть недоступна."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Изменить разрешения браузера для доступа к географическому местоположению"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Позволяет программе изменять разрешения браузера для доступа к географическому положению. Вредоносные программы могут пользоваться этим для отправки информации о местоположении на некоторые сайты."</string>
<string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Найдена доступная сеть Wi-Fi"</item>
<item quantity="other" msgid="7915895323644292768">"Найдены доступные сети Wi-Fi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Введите символ"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Неизвестное приложение"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Отправка SMS-сообщений"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Подключен как устройство хранения данных"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Подключен как камера"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Подключен как установщик"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Нажмите, чтобы увидеть другие параметры USB"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирование"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Очистить SD-карту"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d836312..4af1a79 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Umožňuje aplikáciám sledovať, ktoré klávesy používate, a to aj pri práci s inými aplikáciami (napríklad pri zadávaní hesla). Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"väzba na metódu vstupu"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania metódy vstupu. Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie vôbec nemali využívať."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provincia"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"PSČ"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Štát"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"PSČ"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Kraj"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ostrov"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Okres"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Oddelenie"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektúra"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Farnosť"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Oblasť"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirát"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Čítanie histórie a záložiek prehliadača"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikácii čítať všetky adresy URL navštívené prehliadačom a záložky prehliadača."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Zapisovať históriu a záložky prehliadača"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umožňuje aplikácii zmeniť históriu prehliadača alebo záložky uložené v telefóne. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť údaje prehliadača."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"nastaviť budík"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Umožní aplikácii nastaviť budík v nainštalovanej aplikácii budíka. Niektoré aplikácie budíka nemusia túto funkciu obsahovať."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Zmeniť oprávnenia prehliadača poskytovať informácie o zemepisnej polohe"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikácii zmeniť oprávnenie prehliadača poskytovať informácie o zemepisnej polohe. Škodlivé aplikácie môžu toto nastavenie použiť na odosielanie informácií o umiestnení na ľubovoľné webové stránky."</string>
<string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prehliadač zapamätal toto heslo?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"K dispozícii je verejná sieť Wi-Fi"</item>
<item quantity="other" msgid="7915895323644292768">"K dispozícii sú verejné siete Wi-Fi"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Vkladanie znakov"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznáma aplikácia"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Odosielanie správ SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Pripojené ako mediálne zariadenie"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Pripojené ako fotoaparát"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Pripojené ako inštalátor"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Dotykom zobrazíte ďalšiu možnosť USB"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9c43047..9b45470 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Programu dovoljuje spremljanje tipk, ki jih pritisnete med interakcijo z drugim programom (na primer vnos gesla). Navadni programi tega nikoli ne potrebujejo."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"povezovanje z načinom vnosa"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Dovoljuje lastniku, da se poveže z vmesnikom načina vnosa najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezovanje z ozadjem"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Dovoljuje, da se lastnik poveže z vmesnikom ozadja najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provinca"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Poštna številka"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Zvezna država"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Poštna številka"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Okrožje"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Otok"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Okraj"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Departma"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektura"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Župnija"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Območje"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"branje zgodovine in zaznamkov brskalnika"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Programu dovoljuje branje vseh URL-jev, ki jih je brskalnik obiskal, in vseh brskalnikovih zaznamkov."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje zgodovine in zaznamkov brskalnika"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Programu dovoljuje spreminjanje zgodovine brskalnika ali zaznamkov, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov brskalnika."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"nastavitev alarma budilke"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Programu omogoča nastavitev alarma v nameščeni budilki. Nekatere budilke morda ne bodo uporabile te funkcije."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Spreminjanje dovoljenj za geolokacijo brskalnika"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Programu dovoljuje spreminjanje dovoljenja brskalnika za geografske lokacije. Zlonamerni programi lahko s tem dovoljenjem dovolijo pošiljanje podatkov o lokaciji poljubnim spletnim mestom."</string>
<string name="save_password_message" msgid="767344687139195790">"Ali želite, da si brskalnik zapomni to geslo?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Odpiranje razpoložljivega brezžičnega omrežja"</item>
<item quantity="other" msgid="7915895323644292768">"Odpiranje razpoložljivih brezžičnih omrežij"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Vstavljanje znaka"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Neznan program"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Pošiljanje sporočil SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Povezan kot predstavnostna naprava"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Povezan kot fotoaparat"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Povezan kot namestitveni program"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Dotaknite se, če želite izbrati druge možnosti za USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Prstni odtis SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Prstni odtis SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Prikaži vse ..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Izberite dejavnost"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Skupna raba z ..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index ec6470e..4d25343 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Омогућава да апликације виде које тастере притискате чак и док радите у некој другој апликацији (нпр. када уносите лозинку). Нормалне апликације никада не би требало да је користе."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"обавезивање на методу уноса"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Омогућава власнику да се обавеже на интерфејс методе уноса највишег нивоа. Обичне апликације никада не би требало да је користе."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"обавезивање на позадину"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Омогућава власнику да се обавеже на интерфејс позадине највишег нивоа. Обичне апликације никада не би требало да је користе."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Покрајина"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Поштански број"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Држава"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Поштански број"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Округ"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Острво"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Дистрикт"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Одељење"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Префектура"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Парохија"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Област"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Емират"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читање историје и обележивача у прегледачу"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Омогућава да апликација чита све URL адресе које су посећене у прегледачу, као и све обележиваче у њему."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"уписивање историје и обележивача из прегледача"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Омогућава да апликација измени историју и обележиваче у прегледачу сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке у прегледачу."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"подешавање аларма у будилнику"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозвољава да апликација подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Измена дозвола за географске локације прегледача"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Омогућава да апликација измени дозволе за утврђивање географске локације у прегледачу. Злонамерне апликације то могу да злоупотребе и искористе за слање информација о локацији насумичним веб сајтовима."</string>
<string name="save_password_message" msgid="767344687139195790">"Желите ли да прегледач запамти ову лозинку?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Доступна је отворена Wi-Fi мрежа"</item>
<item quantity="other" msgid="7915895323644292768">"Доступне су отворене Wi-Fi мреже"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Уметање знака"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Непозната апликација"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Слање SMS порука"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Повезан као медијски уређај"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Повезан као камера"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Повезан као инсталациони програм"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Додирните за друге USB опције"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d7bc859..3de0006b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Tillåter att program övervakar knapparna som du trycker på, till och med när du använder andra program (till exempel när du anger ett lösenord). Ska inte behövas för vanliga program."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"binda till en metod för indata"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en inmatningsmetod. Ska inte behövas för vanliga program."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"binda till en bakgrund"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en bakgrund. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Provins"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postnummer"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Delstat"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Postnummer"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Kommun"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ö"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrikt"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Department"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefektur"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Församling"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Område"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"läsa webbläsarhistorik och bokmärken"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Tillåter att program läser alla webbadresser som webbläsaren har öppnat och alla webbläsarens bokmärken."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"skriva webbläsarhistorik och bokmärken"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Tillåter att ett program ändrar webbläsarhistoriken och bokmärkena i din telefon. Skadliga program kan använda detta för att ta bort eller ändra data i webbläsaren."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"ställa in alarm i alarmklocka"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Tillåter att programmet ställer in ett alarm i ett installerat alarmprogram. Vissa alarmprogram har inte den här funktionen."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ändra geografisk plats för webbläsaren"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Tillåter att ett program ändrar webbläsarens behörigheter för geografisk plats. Skadliga program kan använda detta för att tillåta att platsinformation skickas till godtyckliga webbplatser."</string>
<string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
<item quantity="other" msgid="7915895323644292768">"Öppna Wi-Fi-nätverk är tillgängliga"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Infoga tecken"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Okänd app"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Skickar SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Ansluten som en mediaenhet"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Ansluten som en kamera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Ansluten som installationsprogram"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Tryck för andra USB-alternativ"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256-fingeravtryck"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1-fingeravtryck:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Visa alla..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Välj aktivitet"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Dela med..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 6d7de63..d2c62bf 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -385,6 +385,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Huruhusu programu kutazama vitufe unavyobofya hata wakati unaingiliana na programu nyingine ya kompyuta (kama vile kuingiza nenosiri). Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"funganisha kwa mbinu ya uingizaji"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha mbinu ya uingizaji. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa pazia"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Huruhusu kishikiliaji kufunga kiolesura cha kiwango cha juu cha pazia. Haipaswi kuhitajika kwa programu za kawaida za kompyuta."</string>
<!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -962,6 +966,10 @@
<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>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Rekebisha vibali vya Kivinjari cha eneo la jiografia"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Huruhusu programu kwa kurekebisha vibali vya Kivinjari cha eneo la jeo. Programu hasidi zinaweza kutumia hii kwa kuruhusu utumaji wa habari ya eneo kwa tovuti mbadala."</string>
<!-- no translation found for save_password_message (767344687139195790) -->
@@ -1216,6 +1224,22 @@
<item quantity="one" msgid="1634101450343277345">"Fungua mtandao wa Wi-Fi unaopatikana"</item>
<item quantity="other" msgid="7915895323644292768">"Fungua mitandao ya Wi-Fi inayopatikana"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Ingiza kibambo"</string>
<!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
<skip />
@@ -1277,6 +1301,8 @@
<skip />
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<!-- no translation found for usb_notification_message (4447869605109736382) -->
<skip />
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fomati hifadhi ya USB"</string>
@@ -1465,4 +1491,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw600dp/colors.xml b/core/res/res/values-sw600dp/colors.xml
new file mode 100644
index 0000000..6b5a55a
--- /dev/null
+++ b/core/res/res/values-sw600dp/colors.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <!-- keyguard clock -->
+ <color name="lockscreen_clock_background">#b3ffffff</color>
+ <color name="lockscreen_clock_foreground">#7affffff</color>
+ <color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
+ <color name="lockscreen_owner_info">#ff9a9a9a</color>
+
+</resources>
+
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a75929f..0e1e8c1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"อนุญาตให้แอปพลิเคชันดูปุ่มที่คุณกดแม้ในระหว่างที่ทำงานร่วมกับแอปพลิเคชันอื่น (เช่น ป้อนรหัสผ่าน) ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"เชื่อมโยงกับวิธีป้อนข้อมูล"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"อนุญาตให้ผู้ถือเชื่อมโยงกับอินเทอร์เฟซระดับสูงสุดของวิธีป้อนข้อมูล ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"เชื่อมโยงกับวอลเปเปอร์"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"อนุญาตให้ผู้ถือเชื่อมโยงกับอินเทอร์เฟซระดับสูงสุดของวอลเปเปอร์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"จังหวัด"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"รหัสไปรษณีย์"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"รัฐ"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"รหัสไปรษณีย์"</string>
+ <string name="autofill_county" msgid="237073771020362891">"อำเภอ"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"เกาะ"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"เขต"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"แผนก"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"เขตปกครอง"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"เขตการปกครองท้องถิ่น"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"พื้นที่"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"เอมิเรต"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"อ่านประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"อนุญาตให้แอปพลิเคชันอ่าน URL ทั้งหมดที่เบราว์เซอร์เคยเข้าชมและบุ๊กมาร์กของเบราว์เซอร์ทั้งหมด"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"เขียนประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"อนุญาตให้แอปพลิเคชันแก้ไขประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลเบราว์เซอร์ของคุณได้"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"ตั้งเวลาปลุกในนาฬิกาปลุก"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"อนุญาตให้แอปพลิเคชันนี้ตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้งไว้ แอปพลิเคชันนาฬิกาปลุกบางประเภทอาจไม่ใช้คุณลักษณะนี้"</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้อนุญาตให้ส่งข้อมูลตำแหน่งไปที่เว็บไซต์อื่นได้โดยพลการ"</string>
<string name="save_password_message" msgid="767344687139195790">"คุณต้องการให้เบราว์เซอร์จำรหัสผ่านนี้หรือไม่"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
<item quantity="other" msgid="7915895323644292768">"เปิดเครือข่าย Wi-Fi ที่ใช้งานได้"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"ใส่อักขระ"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"ไม่ทราบแอปพลิเคชัน"</string>
<string name="sms_control_title" msgid="7296612781128917719">"กำลังส่งข้อความ SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"เชื่อมต่อเป็นอุปกรณ์สื่อ"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"เชื่อมต่อเป็นกล้องถ่ายรูป"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"เชื่อมต่อเป็นตัวติดตั้ง"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"แตะสำหรับตัวเลือก USB อื่นๆ"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"ลายนิ้วมือ SHA-256"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"ลายนิ้วมือ SHA-1"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"ดูทั้งหมด..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"เลือกกิจกรรม"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"แบ่งปันกับ..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 55209f4..12c14c3 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Pinapayagan ang mga application na panoorin ang mga pinipindot mong key maging kapag nakikipag-ugnay sa isa pang application (gaya ng pagpasok ng password). Hindi dapat na kailanganin kailanman para sa mga normal na application."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"sumailalim sa isang pamamaraan ng pag-input"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Pinapayagan ang holder na sumailalim sa nangungunang antas na interface ng pamamaraan ng pag-input. Hindi dapat kailanmang kailanganin para sa mga normal na application."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sumailalim sa wallpaper"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Pinapayagan ang holder na sumailalim sa interface na nasa nangungunang antas ng wallpaper. Hindi kailanman dapat na kailanganin para sa mga normal na application."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Lalawigan"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Postal code"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Estado"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"ZIP code"</string>
+ <string name="autofill_county" msgid="237073771020362891">"County"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Pulo"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Distrito"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Kagawaran"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Prefecture"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Parokya"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Lugar"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirate"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"basahin ang kasaysayan at mga bookmark ng Browser"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Pinapayagan ang application na basahin ang lahat ng URL na binisita ng Browser, at lahat ng bookmark ng Browser."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"isulat ang kasaysayan ng Browser at mga bookmark"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Pinapayagan ang isang application na baguhin ang kasaysayan o mga bookmark ng Browser na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng Browser."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"itakda ang alarm sa alarm clock"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Pinapayagan ang application na magtakda ng alarm sa isang naka-install na application ng alarm clock. Maaaring hindi ipatupad ng ilang application ng alarm clock ang tampok na ito."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Baguhin ang mga pahintulot ng Browser geolocation"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Pinapayagan ang isang application na baguhin ang mga pahintulot sa geolocation ng Browser. Magagamit ito ng mga nakakahamak na application upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi saklaw na web site."</string>
<string name="save_password_message" msgid="767344687139195790">"Gusto mo bang tandaan ng browser ang password na ito?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Available ang bukas na Wi-Fi network"</item>
<item quantity="other" msgid="7915895323644292768">"Buksan ang mga available na Wi-Fi network"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Magpasok ng character"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Hindi kilalang application"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Nagpapadala ng mga SMS na mensahe"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Nakakonekta bilang isang media device"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Nakakonekta bilang isang camera"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Nakakonekta bilang isang installer"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"I-touch para sa mga ibang pagpipilian sa USB"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"SHA-256 na fingerprint:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"SHA-1 na fingerprint:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Tingnan lahat..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Pumili ng aktibidad"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Ibahagi sa..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index b4a6922..ca29d65 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Uygulamaların, başka bir uygulama ile etkileşim halindeyken (örneğin bir şifre girerken) bile bastığınız tuşları izlemesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"bir giriş yöntemine bağla"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Tutucunun bir giriş yönteminin en üst düzey arayüzüne bağlanmasına izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"bir duvar kağıdına tabi kıl"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Hesap sahibine bir duvar kağıdının en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmamalıdır."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Vilayet"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Posta kodu"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Eyalet"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Posta kodu"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Belde"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Ada"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"İlçe"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Bölüm"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"İdari Bölge"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Mahalle"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Alan"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Emirlik"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Tarayıcı geçmişini ve favorileri oku"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Uygulamaya Tarayıcının ziyaret etmiş olduğu tüm URL\'leri ve Tarayıcının tüm favorilerini okuma izni verir."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Tarayıcı geçmişini ve favorileri yaz"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Uygulamaya telefonunuzda depolanan Tarayıcı geçmişini veya favorileri değiştirme izni verir. Kötü amaçlı uygulamalar bunu Tarayıcı verilerinizi silmek veya değiştirmek için kullanabilir."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"çalar saatte alarm ayarla"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Uygulamanın yüklü bir çalar saat uygulamasında bir alarm ayarlamasına izin verir. Bazı çalar saat uygulamaları bu özelliği kullanmayabilir."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Bir uygulamanın, Tarayıcı\'nın coğrafi konum izinlerini değiştirmesine izin verir. Kötü amaçlı uygulamalar, bu özelliği konum bilgilerini rastgele web sitelerine göndermek için kullanabilir."</string>
<string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Kullanılabilir kablosuz ağı aç"</item>
<item quantity="other" msgid="7915895323644292768">"Kullanılabilir kablosuz ağları aç"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Karakter ekle"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Bilinmeyen uygulama"</string>
<string name="sms_control_title" msgid="7296612781128917719">"SMS mesajları gönderiliyor"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Medya cihazı olarak bağlandı"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Kamera olarak bağlandı"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Yükleyici olarak bağlandı"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Diğer USB seçenekleri için dokunun"</string>
<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>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e813b92..5a4a34c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Дозволяє програмі переглядати клавіші, які ви натискаєте, навіть під час роботи з іншою програмою (наприклад, під час вводу пароля). Ніколи не потрібний для звичайних програм."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"прив\'яз. до методу введ."</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Дозволяє власнику прив\'язувати до інтерфейсу верхнього рівня методу введення. Ніколи не потрібний для звичайних програм."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"прив\'зати до фон. мал."</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Дозволяє власнику прив\'язувати до інтерфейсу верхнього рівня фон. малюнка. Ніколи не потрібний для звичайних програм."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string>
@@ -720,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Дозволяє програмі змінювати історію чи закладки переглядача, збережені у вашому тел. Шкідливі програми можуть викор. це, щоб видаляти чи змінювати дані переглядача."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"налашт. сигнал у будильн."</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Змін. дозволи геогр. місцезн. перегладача"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Дозволяє програмі змін. дозволи географ. місцезн. переглядача. Шкідливі програми можуть використ. це, щоб дозволяти надсилати інф-ю про місцезн. випадковим веб-сайтам."</string>
<string name="save_password_message" msgid="767344687139195790">"Хочете, щоб переглядач запам\'ятав цей пароль?"</string>
@@ -911,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Відкрита Wi-Fi мережа доступна"</item>
<item quantity="other" msgid="7915895323644292768">"Відкриті Wi-Fi мережі доступні"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Вставл-ня символу"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Невідома програма"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Надсил. SMS повідомлень"</string>
@@ -959,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Під’єднано як носій"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Під’єднано як камеру"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Під’єднано як програму встановлення"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Торкніться, щоб побачити інші параметри USB"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string>
@@ -1106,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Відбиток SHA-256"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Відбиток SHA-1"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Показати всі..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Вибрати дію"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Надіслати..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index dd2c19d..a754a5c 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Cho phép ứng dụng xem các phím bạn nhấn ngay cả khi tương tác với ứng dụng khác (chẳng hạn như nhập mật khẩu). Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"liên kết với phương thức nhập"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Cho phép chủ nhân ràng buộc với giao diện cấp cao nhất của phương thức nhập. Không cần thiết cho các ứng dụng thông thường."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"liên kết với hình nền"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Cho phép chủ nhân ràng buộc với giao diện cấp cao nhất của hình nền. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"Tỉnh"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"Mã bưu chính"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"Tiểu bang"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"Mã ZIP"</string>
+ <string name="autofill_county" msgid="237073771020362891">"Hạt"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"Đảo"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"Quận"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"Khu hành chính"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"Quận"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"Giáo xứ"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"Khu vực"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"Tiểu vương quốc Ả rập"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"đọc lịch sử và dấu trang của Trình duyệt"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Cho phép ứng dụng đọc tất cả các URL mà Trình duyệt đã truy cập và tất cả các dấu trang của Trình duyệt."</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"xem lịch sử và dấu trang của Trình duyệt"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt đượ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 Trình duyệt của bạn."</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"đặt báo thức trong đồng hồ báo thức"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không sử dụng tính năng này."</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Sửa đổi quyền về vị trí địa lý của Trình duyệt"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Cho phép ứng dụng sửa đổi các quyền về vị trí địa lý của Trình duyệt. Các ứng dụng độc hại có thể sử dụng quyền này để cho phép gửi thông tin vị trí đến trang web bất kỳ."</string>
<string name="save_password_message" msgid="767344687139195790">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"Mở mạng Wi-Fi khả dụng"</item>
<item quantity="other" msgid="7915895323644292768">"Mở mạng Wi-Fi khả dụng"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Chèn ký tự"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"Ứng dụng không xác định"</string>
<string name="sms_control_title" msgid="7296612781128917719">"Đang gửi tin nhắn SMS"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"Đã kết nối là thiết bị truyền thông"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Đã kết nối như máy ảnh"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Được kết nối như trình cài đặt"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"Chạm để có các tùy chọn USB khác"</string>
<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>
@@ -1118,8 +1132,8 @@
<string name="sha256_fingerprint" msgid="4391271286477279263">"Tệp tham chiếu SHA-256:"</string>
<string name="sha1_fingerprint" msgid="7930330235269404581">"Tệp tham chiếu SHA-1:"</string>
<string name="activity_chooser_view_see_all" msgid="180268188117163072">"Xem tất cả..."</string>
- <!-- no translation found for activity_chooser_view_dialog_title_default (3325054276356556835) -->
- <skip />
- <!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
+ <string name="activity_chooser_view_dialog_title_default" msgid="3325054276356556835">"Chọn hoạt động"</string>
+ <string name="share_action_provider_share_with" msgid="1791316789651185229">"Chia sẻ với..."</string>
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
<skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 0fb0106..6daa793 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"允许应用程序查看您按的键,即使在与其他应用程序交互(例如输入密码)时也不例外。普通应用程序从不需要使用此权限。"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"绑定至输入法"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允许手机用户绑定至输入法的顶级界面。普通应用程序从不需要使用此权限。"</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允许手机用户绑定到壁纸的顶级界面。应该从不需要将此权限授予普通应用程序。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到窗口小部件服务"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"省/直辖市/自治区"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"邮政编码"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"州"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"邮政编码"</string>
+ <string name="autofill_county" msgid="237073771020362891">"郡"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"岛"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"地区"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"省"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"县/府/都/道"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"行政区"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"区域"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"酋长国"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"读取浏览器的历史记录和书签"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允许应用程序读取用浏览器访问过的所有网址,以及浏览器的所有书签。"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"写入浏览器的历史记录和书签"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"允许应用程序修改存储在手机中的浏览器历史记录或书签。恶意应用程序可借此清除或修改浏览器数据。"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"在闹钟中设置警报"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"允许应用程序在安装的闹钟应用程序中设置警报。某些闹钟应用程序没有实现此功能。"</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改浏览器的地理位置权限"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允许应用程序修改浏览器的地理位置权限。恶意应用程序会利用这一点将位置信息发送到任意网站。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"打开可用的 Wi-Fi 网络"</item>
<item quantity="other" msgid="7915895323644292768">"打开可用的 Wi-Fi 网络"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"插入字符"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"未知的应用程序"</string>
<string name="sms_control_title" msgid="7296612781128917719">"正在发送短信"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"作为媒体设备连接"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"作为相机连接"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"作为安装程序连接"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"触摸可显示其他 USB 选项"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 存储设备"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"格式化 SD 卡"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index bf33dbf..411b24f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -262,6 +262,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"允許應用程式在使用者操作其他程式時 (例如:輸入密碼),仍可監看輸入的按鍵。一般應用程式應不需要此功能。"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"連結至輸入法"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允許擁有人連結至輸入法的最頂層介面。一般應用程式不需使用此選項。"</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允許擁有人連結至桌布的最頂層介面,一般應用程式不需使用此選項。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
@@ -701,30 +705,18 @@
<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>
- <!-- no translation found for autofill_province (2231806553863422300) -->
- <skip />
- <!-- no translation found for autofill_postal_code (4696430407689377108) -->
- <skip />
- <!-- no translation found for autofill_state (6988894195520044613) -->
- <skip />
- <!-- no translation found for autofill_zip_code (8697544592627322946) -->
- <skip />
- <!-- no translation found for autofill_county (237073771020362891) -->
- <skip />
- <!-- no translation found for autofill_island (4020100875984667025) -->
- <skip />
- <!-- no translation found for autofill_district (8400735073392267672) -->
- <skip />
- <!-- no translation found for autofill_department (5343279462564453309) -->
- <skip />
- <!-- no translation found for autofill_prefecture (2028499485065800419) -->
- <skip />
- <!-- no translation found for autofill_parish (8202206105468820057) -->
- <skip />
- <!-- no translation found for autofill_area (3547409050889952423) -->
- <skip />
- <!-- no translation found for autofill_emirate (2893880978835698818) -->
- <skip />
+ <string name="autofill_province" msgid="2231806553863422300">"省"</string>
+ <string name="autofill_postal_code" msgid="4696430407689377108">"郵遞區號"</string>
+ <string name="autofill_state" msgid="6988894195520044613">"州/省"</string>
+ <string name="autofill_zip_code" msgid="8697544592627322946">"郵遞區號"</string>
+ <string name="autofill_county" msgid="237073771020362891">"縣/市"</string>
+ <string name="autofill_island" msgid="4020100875984667025">"島"</string>
+ <string name="autofill_district" msgid="8400735073392267672">"行政區"</string>
+ <string name="autofill_department" msgid="5343279462564453309">"省"</string>
+ <string name="autofill_prefecture" msgid="2028499485065800419">"縣"</string>
+ <string name="autofill_parish" msgid="8202206105468820057">"教區"</string>
+ <string name="autofill_area" msgid="3547409050889952423">"區"</string>
+ <string name="autofill_emirate" msgid="2893880978835698818">"大公國"</string>
<string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"讀取瀏覽器的記錄與書籤"</string>
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
@@ -732,6 +724,10 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。"</string>
<string name="permlab_setAlarm" msgid="5924401328803615165">"在鬧鐘應用程式中設定鬧鈴"</string>
<string name="permdesc_setAlarm" msgid="5966966598149875082">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改瀏覽器地理資訊的權限"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允許應用程式修改瀏覽器的地理位置權限,惡意應用程式可能會透過此方式允許將您的位置資訊任意傳送給某些網站。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
@@ -923,6 +919,22 @@
<item quantity="one" msgid="1634101450343277345">"開啟可用 Wi-Fi 網路"</item>
<item quantity="other" msgid="7915895323644292768">"開啟可用 Wi-Fi 網路"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"插入字元"</string>
<string name="sms_control_default_app_name" msgid="7630529934366549163">"未知的應用程式"</string>
<string name="sms_control_title" msgid="7296612781128917719">"傳送 SMS 簡訊"</string>
@@ -971,6 +983,8 @@
<string name="usb_mtp_notification_title" msgid="3699913097391550394">"已視為媒體裝置連線"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"已視為相機連線"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"已視為安裝程式連線"</string>
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<string name="usb_notification_message" msgid="4447869605109736382">"輕觸即可顯示其他 USB 選項"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"格式化 USB 儲存空間"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"將 SD 卡格式化"</string>
@@ -1122,4 +1136,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 0e05ad5..f224e63 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -191,8 +191,8 @@
<!-- no translation found for contentServiceSyncNotificationTitle (397743349191901458) -->
<skip />
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Kunokususa <xliff:g id="CONTENT_TYPE">%s</xliff:g> okuningi kakhulu."</string>
- <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>
+ <string name="low_memory" product="tablet" msgid="2292820184396262278">"Isitoreji sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
+ <!-- outdated translation 2292820184396262278 --> <string name="low_memory" product="default" msgid="6632412458436461203">"Isitoreji sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
<!-- no translation found for me (6545696007631404292) -->
<skip />
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Okukhethwa kukho kwethebhulethi"</string>
@@ -265,8 +265,8 @@
<!-- no translation found for permgrouplab_developmentTools (3446164584710596513) -->
<skip />
<string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Izici zidingeka kuphela konjiniyela bohlelo lokusebenza."</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukugcina"</string>
- <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kukugcina nge-USB."</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Isitoreji"</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Finyelela kwisitoreji se-USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Finyelela ikhadi le-SD."</string>
<!-- no translation found for permlab_statusBar (7417192629601890791) -->
<skip />
@@ -322,7 +322,7 @@
<string name="permlab_enableCarMode" msgid="5684504058192921098">"vumela imodi yemoto"</string>
<string name="permdesc_enableCarMode" msgid="5673461159384850628">"Ivumela uhlelo lokusebenza ukuvumela imodi yemoto."</string>
<string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"bulala izinqubo zasemuva"</string>
- <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ivumela uhlelo lokusebenza ukubulala izinqubo zasemuva zezinye izinhlelo zokusebenza, ngisho noma inkumbulo iphansi kakhulu."</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Ivumela uhlelo lokusebenza ukubulala izinqubo zasemuva zezinye izinhlelo zokusebenza, ngisho noma imemori iphansi kakhulu."</string>
<string name="permlab_forceStopPackages" msgid="1447830113260156236">"phoqelela ukumisa ezinye izinhlelo zokusebenza"</string>
<string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Ivumela uhlelo lokusebenza ukumisa ngokuphoqelela ezinye izinhlelo zokusebenza."</string>
<!-- no translation found for permlab_forceBack (1804196839880393631) -->
@@ -385,6 +385,10 @@
<string name="permdesc_readInputState" msgid="5132879321450325445">"Ivumela izinhlelo zokusebenza ukufunda izinkinobho ozicindezela ngisho noma uxhumana nolunye uhlelo lokusebenza (njengokufaka iphasiwedi). Akusoze kwadingeka ezinhlelweni zokusebenza ezivamile."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"hlanganisa indlela yokufakwayo"</string>
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"Ivumela isimeli ukuhlanganisa uxhumano nomsebenzisi wezinga eliphezulu lendlela yokufaka. Ayisoze yadingeka kwizinhlelo ezivamile."</string>
+ <!-- no translation found for permlab_bindTextService (7358378401915287938) -->
+ <skip />
+ <!-- no translation found for permdesc_bindTextService (172508880651909350) -->
+ <skip />
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"hlanganisa kwiphephadonga"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwephephadonga. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
<!-- no translation found for permlab_bindRemoteViews (5697987759897367099) -->
@@ -422,8 +426,8 @@
<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 />
- <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="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ivumela uhlelo lokusebenza ukukhulula isitoreji sethebhulethi ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqubweni yesistimu."</string>
+ <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ivumela uhlelo lokusebenza ukukhulula isitoreji sefoni ngokususa amafayela kwisiqondiso sesilondolozi sesikhashana sohlelo lokusebenza. Ukufinyelele ngokuvamile kuvinjelwe enqutshweni yesitimu."</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>
@@ -454,7 +458,7 @@
<!-- no translation found for permlab_broadcastSticky (7919126372606881614) -->
<skip />
<string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ivumela uhlelo lokusebenza ukuthumela imisakazo enamathelayo, esala emva kokuba ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya 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>
+ <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ivumela uhlelo lokusebenza ukuthumela imisakazo engazwakali kahle, esala emuva kokuthi ukusakaza kuphelile. Izinhlelo zokusebenza ezinonya zingenza ifoni ingasheshi futhi ingasebenzi kahle ngokuyibangela ukuthi isebenzise imemori eningi kakhulu."</string>
<!-- no translation found for permlab_readContacts (6219652189510218240) -->
<skip />
<string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ivumela uhlelo lokusebenza ukufunda yonke idatha yothintana naye (ikheli) egcinwe kwithebhulethi yakho. Izinhlelo zokusebenza ezinonya zingase zisebenzise lokhu ukuthumela idatha yakho kwabanye abantu."</string>
@@ -516,19 +520,19 @@
<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>
- <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>
+ <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ivumela izinhlelo ukukhweza nokukwehlisa amasistimu wefayela lesitoreji esikhiphekayo."</string>
+ <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"fometha isitoreji sangaphandle"</string>
+ <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ivumela uhlelo lokusebenza ukufometha isitoreji esikhiphekayo."</string>
+ <string name="permlab_asec_access" msgid="3411338632002193846">"thola ulwazi ngesitoreji sangaphakathi"</string>
+ <string name="permdesc_asec_access" msgid="8820326551687285439">"Ivumela uhlelo lokusebenza ukuthola ulwazi ngesitoreji sangaphakathi."</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"dala isitoreji sangaphakathi"</string>
+ <string name="permdesc_asec_create" msgid="2621346764995731250">"Ivumela uhlelo lokusebenza ukudala isitoreji sangaphakathi."</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"yonakalisa isitoreji sangaphakathi"</string>
+ <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ivumela uhlelo lokusebenza ukonakalisa isitoreji sangaphakathi."</string>
+ <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"khweza / yehlisa isitoreji sangaphakathi"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ivumela uhlelo lokusebenza ukukhweza / ukwehlisa isitoreji sangaphakathi."</string>
+ <string name="permlab_asec_rename" msgid="7496633954080472417">"yetha kabusha isitoreji sangaphakathi"</string>
+ <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ivumela uhlelo lokusebenza ukwetha kabusha isitoreji sangaphakathi."</string>
<!-- no translation found for permlab_vibrate (7768356019980849603) -->
<skip />
<string name="permdesc_vibrate" msgid="2886677177257789187">"Ivumela uhlelo lokusebenza ukulawula isidlidlizi."</string>
@@ -550,8 +554,8 @@
<!-- 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>
- <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="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"ngokuqondile qalisa ukumisa ithebhulethi nge-CDMA"</string>
+ <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"ngokuqondile qalisa ukumisa 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) -->
<skip />
@@ -667,12 +671,12 @@
<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>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe kokugcina nge-USB"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"guqula/susa okuqukethwe isitoreji se-USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"guqula/susa okuqukethwe kwekhadi le-SD"</string>
- <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala ekugcineni nge-USB."</string>
+ <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ivumela uhlelo lokusebenza ukubhala kwisitoreji se-USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ivumela uhlelo lokusebenza ukubhala ekhadini le-SD."</string>
- <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_mediaStorageWrite" product="default" msgid="6859839199706879015">"guqula/susa okuqukethwe kwisitoreji semidiya yangaphakathi"</string>
+ <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ivumela uhlelo lokusebenza ukuguqula okuqukethwe kwisitoreji semidiya 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>
<string name="permlab_use_sip" msgid="5986952362795870502">"yena/thola amakholi e-Inthanethi"</string>
@@ -705,7 +709,7 @@
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Misa iphrokzi jikelele yedivaysi ukusebenzisa ngenkathi inqumbomgomo ivunyelwa. Idivaysi yokuqala kuphela yokuphatha emisa ummeleli jikelele esebenzayo."</string>
<!-- 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="policylab_encryptedStorage" msgid="8901326199909132915">"Setha umbhalo wemfihlo yesitoreji"</string>
<string name="policydesc_encryptedStorage" msgid="2504984732631479399">"Idinga ukuba idatha yohlelo lokusebenza olugciniwe ibhalwe ngokufihlekileyo"</string>
<!-- no translation found for policylab_disableCamera (6395301023152297826) -->
<skip />
@@ -962,6 +966,10 @@
<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>
+ <!-- no translation found for permlab_readWriteOwnVoicemail (8861946090046059697) -->
+ <skip />
+ <!-- no translation found for permdesc_readWriteOwnVoicemail (7343490168272921274) -->
+ <skip />
<string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Gugula izimvume zendawo Yesiphequluli"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ivumela uhlelo lokusebenza ukuguqula izimvume zendawo Yesiphequluli. Izinhlelo ezinonya zingase zisebenzise lokhu ukuvumela ukuthumela ukwaziswa kwendawo kwamanye amasayithi ewebhu."</string>
<!-- no translation found for save_password_message (767344687139195790) -->
@@ -1118,8 +1126,8 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"Izenzo zombhalo"</string>
<!-- no translation found for low_internal_storage_view_title (1399732408701697546) -->
<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>
+ <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Isitoreji sethebhulethi siya ngokuphela."</string>
+ <!-- outdated translation 4231085657068852042 --> <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Isitoreji sethebhulethi siya ngokuphela."</string>
<!-- no translation found for ok (5970060430562524910) -->
<skip />
<!-- no translation found for cancel (6442560571259935130) -->
@@ -1216,6 +1224,22 @@
<item quantity="one" msgid="1634101450343277345">"Vula inethiwekhi ye-Wi-Fi etholakalayo"</item>
<item quantity="other" msgid="7915895323644292768">"Vula amanethiwekhi we-Wi-Fi atholakalayo"</item>
</plurals>
+ <!-- no translation found for wifi_watchdog_network_disabled (6398650124751302012) -->
+ <skip />
+ <!-- no translation found for wifi_watchdog_network_disabled_detailed (4659127251774069612) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_turnon_message (2804722042556269129) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_failed_message (6467545523417622335) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pbc_go_negotiation_request_message (3170321684621420428) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_go_negotiation_request_message (5177412094633377308) -->
+ <skip />
+ <!-- no translation found for wifi_p2p_pin_display_message (2834049169114922902) -->
+ <skip />
<string name="select_character" msgid="3365550120617701745">"Faka uhlamvu"</string>
<!-- no translation found for sms_control_default_app_name (7630529934366549163) -->
<skip />
@@ -1248,27 +1272,27 @@
<skip />
<string name="perms_hide" msgid="7283915391320676226"><b>"Fihla "</b></string>
<string name="perms_show_all" msgid="2671791163933091180"><b>"Bonisa konke"</b></string>
- <string name="usb_storage_activity_title" msgid="2399289999608900443">"Ukugcina Okukhulu nge-USB"</string>
+ <string name="usb_storage_activity_title" msgid="2399289999608900443">"Isitoreji Sokukhulu se-USB"</string>
<!-- no translation found for usb_storage_title (5901459041398751495) -->
<skip />
- <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="nosdcard" msgid="6631094834151575841">"Uxhumeke kwikhompyutha yakho nge-USB. Thinta inkinobho engenzansi uma ufuna ukukopisha amafayela phakathi kwekhompyutha yakho nesitoreji se-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>
- <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>
+ <string name="usb_storage_button_mount" msgid="1052259930369508235">"Vula isitoreji se-USB"</string>
+ <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Kunenkinga yokusebenzisa ikhadi lakho le-SD njengesitoreji se-USB."</string>
+ <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Kunenkinga yokusebenzisa ikhadi lakho le-SD njengesitoreji se-USB."</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">"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>
- <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>
- <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Vula ukugcina nge-USB"</string>
- <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="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vala isitoreji se-USB"</string>
+ <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Khetha ukuvala isitoreji se-USB."</string>
+ <string name="usb_storage_stop_title" msgid="660129851708775853">"Isitoreji se-USB siyasebenza"</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Ngaphambi kokuvala kwisitoreji se-USB, qiniseka ukuthi wehlise (\"ukhiphe\") isitoreji se-USB se-Android yakho kwikhompyutha yakho."</string>
+ <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Ngaphambi kokuvala isitoreji se-USB, qiniseka ukuthi wehlise (\"ukhiphe\" ikhadi lakho le-Android SD kwikhompyutha yakho."</string>
+ <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vala isitoreji se-USB"</string>
+ <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Kube nenkinga yokuvala isitoreji se-USB. Hlola ukuqiniseka ukuthi wehlise isikhungo se-USB, bese uzama futhi."</string>
+ <string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"Vula isitoreji se-USB"</string>
+ <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Uma uvula isitoreji se-USB, ezinye izinhlelo zokusebenza ozisebenzisayo zizoma futhi zingase zingatholakali kuze kube yilapho uvala isitoreji se-USB."</string>
<string name="dlg_error_title" msgid="8048999973837339174">"Umsebenzi we-USB wehlulekile"</string>
<string name="dlg_ok" msgid="7376953167039865701">"KULUNGILE"</string>
<!-- no translation found for usb_mtp_notification_title (3699913097391550394) -->
@@ -1277,11 +1301,13 @@
<skip />
<!-- no translation found for usb_cd_installer_notification_title (6774712827892090754) -->
<skip />
+ <!-- no translation found for usb_accessory_notification_title (7848236974087653666) -->
+ <skip />
<!-- no translation found for usb_notification_message (4447869605109736382) -->
<skip />
- <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fometha ukugcina nge-USB"</string>
+ <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Fometha isitoreji se-USB"</string>
<string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Fometha ikhadi le=SD"</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="nosdcard" msgid="8296908079722897772">"Fometha isitoreji se-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>
@@ -1292,28 +1318,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>
- <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungiselela ukugcina nge-USB"</string>
+ <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ilungiselela isitoreji se-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>
- <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Ukugcina nge-USB okungenalutho"</string>
+ <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Isitoreji se-USB esingenalutho"</string>
<string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Ikhadi le-SD elingenalutho"</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="nosdcard" msgid="8623130522556087311"></string>
<string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Ikhadi le-SD alinalutho noma lunohlelo lwesistimu olungasekelwa."</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="nosdcard" msgid="2090046769532713563">"Isitoreji se-USB esonakele"</string>
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Ikhadi le-SD elonakele"</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="nosdcard" msgid="529021299294450667">"Isitoreji se-USB konakele. Kungase kudingeke ulifomethe kabusha."</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Ikhadi le-SD lonakele. Kungase kudingeke ukuba uyifomethe futhi."</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="nosdcard" msgid="1661683031330951073">"Isitoreji se-USB sikhishwe ngokungalindelekile"</string>
<string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Ikhadi le-SD likhishwe ngokungalindelekile"</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="nosdcard" msgid="4329848819865594241">"Yehlisa ikhadi le-SD ngaphambi kokukhipha isitoreji se-USB 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>
- <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="nosdcard" msgid="3967973893270360230">"Sekuphephile ukukhipha isitoreji se-USB"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kuphephile ukukhipha 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="nosdcard" msgid="6142195361606493530">"Ungakhipha ngokuvikelekile isitoreji se-USB."</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Ungakhipha ngokuphephile ikhadi le-SD."</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="nosdcard" msgid="4486377230140227651">"Isitoreji se-USB sikhishiwe"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Ikhadi le-SD elikhishiwe"</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="nosdcard" msgid="6921126162580574143">"Isitoreji se-USB sikhishiwe. 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>
@@ -1321,7 +1347,7 @@
<string name="permlab_copyProtectedData" msgid="1660908117394854464">"Ivumela uhlelo lokusebenza ukucelela insizakalo yesiqukathi esimisiwe ukukopisha kokuqukethwe. Ayisebenziswa izinhlelo zokusebenza ezivamile."</string>
<string name="permdesc_copyProtectedData" msgid="537780957633976401">"Ivumela ukucelela insizakalo yesiqukathi esimisiwe ukukopisha kokuqukethwe. Ayisebenziselwa izinhlelo zokusebenza ezivamile."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Thepha kabili ukuthola ukulawula ukusondeza"</string>
- <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Iphutha lesinqunjwana"</string>
+ <string name="gadget_host_error_inflating" msgid="2613287218853846830">"Iphutha lewijethi"</string>
<string name="ime_action_go" msgid="8320845651737369027">"Iya"</string>
<string name="ime_action_search" msgid="658110271822807811">"Sesha"</string>
<string name="ime_action_send" msgid="2316166556349314424">"Thumela"</string>
@@ -1341,7 +1367,7 @@
<string name="input_method_binding_label" msgid="1283557179944992649">"Indlela yokufakwayo"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"Vumelanisaa"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"Ukufinyeleleka"</string>
- <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphepha donga"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
<!-- no translation found for vpn_title (8219003246858087489) -->
<skip />
@@ -1373,17 +1399,17 @@
<item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ku-<xliff:g id="TOTAL">%d</xliff:g>"</item>
</plurals>
<string name="action_mode_done" msgid="7217581640461922289">"Kwenziwe"</string>
- <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Yehlisa ukugcina nge-USB..."</string>
+ <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Yehlisa isitoreji se-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="nosdcard" msgid="4183664626203056915">"Isula isitoreji se-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="nosdcard" msgid="4320339096529911637">"Yehlulekile ukusula isitoreji se-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="nosdcard" msgid="418188720009569693">"Isitoreji se-USB sisahlolwa."</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="nosdcard" msgid="5830814349250834225">"Isitoreji se-USB sisasetshenziswa yikhompyutha."</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>
@@ -1465,4 +1491,6 @@
<skip />
<!-- no translation found for share_action_provider_share_with (1791316789651185229) -->
<skip />
+ <!-- no translation found for status_bar_device_locked (3092703448690669768) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7d7aea9..f80f27d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -616,6 +616,14 @@
buttons. actionBarStyle is still used for the primary
bar. -->
<attr name="actionBarSplitStyle" format="reference" />
+ <!-- Reference to a theme that should be used to inflate widgets
+ and layouts destined for the action bar. Most of the time
+ this will be a reference to the current theme, but when
+ the action bar has a significantly different contrast
+ profile than the rest of the activity the difference
+ can become important. If this is set to @null the current
+ theme will be used.-->
+ <attr name="actionBarWidgetTheme" format="reference" />
<!-- Size of the Action Bar, including the contextual
bar used to present Action Modes. -->
<attr name="actionBarSize" format="dimension" >
@@ -711,9 +719,6 @@
<!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. -->
<attr name="textEditSideNoPasteWindowLayout" format="reference" />
- <!-- Layout of a the view that is used to create the text suggestions popup window in an
- EditText. This window will be displayed below the text line. -->
- <attr name="textEditSuggestionsWindowLayout" format="reference" />
<!-- Layout of the TextView item that will populate the suggestion popup window. -->
<attr name="textEditSuggestionItemLayout" format="reference" />
@@ -2278,6 +2283,8 @@
<flag name="feedbackVisual" value="0x00000008" />
<!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
<flag name="feedbackGeneric" value="0x00000010" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_ALL_MASK} feedback. -->
+ <flag name="feedbackAllMask" value="0xffffffff" />
</attr>
<!-- 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
@@ -3077,9 +3084,6 @@
<!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. -->
<attr name="textEditSideNoPasteWindowLayout" />
- <!-- Layout of a the view that is used to create the text suggestions popup window in an
- EditText. This window will be displayed below the text line. -->
- <attr name="textEditSuggestionsWindowLayout" />
<!-- Layout of the TextView item that will populate the suggestion popup window. -->
<attr name="textEditSuggestionItemLayout" />
@@ -3359,18 +3363,16 @@
The default is LEFT | BASELINE.
See {@link android.widget.GridLayout.LayoutParams#setGravity(int)}. -->
<attr name="layout_gravity" />
- <!-- A value specifying how much deficit or excess width this component can accomodate.
- The default is FIXED. -->
+ <!-- {@deprecated To make a column group lexible, ensure that every component in the
+ group defines a horizontal gravity.} -->
<attr name="layout_columnFlexibility" >
- <!-- If possible, width should be greater than or equal to the specified width.
- See {@link android.widget.GridLayout#CAN_STRETCH}. -->
+ <enum name="inflexible" value="0" />
<enum name="canStretch" value="2" />
</attr>
- <!-- A value specifying how much deficit or excess height this component can accomodate.
- The default is FIXED. -->
+ <!-- {@deprecated To make a row group flexible, ensure that every component in the
+ group defines a vertical gravity.} -->
<attr name="layout_rowFlexibility" >
- <!-- If possible, height should be greater than or equal to the specified height.
- See {@link android.widget.GridLayout#CAN_STRETCH}. -->
+ <enum name="inflexible" value="0" />
<enum name="canStretch" value="2" />
</attr>
</declare-styleable>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 631d8c6..aee7ea4 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,8 +18,8 @@
*/
-->
<resources>
- <drawable name="screen_background_light">#ffffffff</drawable>
- <drawable name="screen_background_dark">#ff000000</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>
<drawable name="search_bar_default_color">#ff000000</drawable>
@@ -75,7 +75,7 @@
<drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
<drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
-
+
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
<drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
@@ -109,14 +109,14 @@
<color name="keyguard_text_color_decline">#fe0a5a</color>
<!-- keyguard clock -->
- <color name="lockscreen_clock_background">#b3ffffff</color>
- <color name="lockscreen_clock_foreground">#7affffff</color>
+ <color name="lockscreen_clock_background">#e5ffffff</color>
+ <color name="lockscreen_clock_foreground">#e5ffffff</color>
<color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
<color name="lockscreen_owner_info">#ff9a9a9a</color>
<!-- For holo theme -->
- <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
- <drawable name="screen_background_holo_dark">#ff000000</drawable>
+ <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_holo_dark">#ff000000</drawable>
<color name="background_holo_dark">#ff000000</color>
<color name="background_holo_light">#fff3f3f3</color>
<color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2b2f356..65dce49 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -469,6 +469,10 @@
speech -->
<bool name="config_bluetooth_wide_band_speech">true</bool>
+ <!-- Boolean indicating if current platform supports quick switch-on/off of
+ Bluetooth Module -->
+ <bool name="config_bluetooth_adapter_quick_switch">true</bool>
+
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 0ed8076..b3e50ea 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -35,7 +35,7 @@
<!-- Height of the system bar -->
<dimen name="system_bar_height">48dip</dimen>
<!-- Height of notification icons in the status bar -->
- <dimen name="status_bar_icon_size">25dip</dimen>
+ <dimen name="status_bar_icon_size">24dip</dimen>
<!-- Size of the giant number (unread count) in the notifications -->
<dimen name="status_bar_content_number_size">48sp</dimen>
<!-- Height of notification icons in the system bar -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b2b7025..0555d10 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1715,7 +1715,6 @@
<public type="attr" name="switchPreferenceStyle" />
<public type="attr" name="textSuggestionsWindowStyle" />
- <public type="attr" name="textEditSuggestionsWindowLayout" />
<public type="attr" name="textEditSuggestionItemLayout" />
<public type="attr" name="suggestionsEnabled" />
@@ -1782,6 +1781,11 @@
<public type="attr" name="actionModeStyle" />
+ <public type="attr" name="minResizeWidth" />
+ <public type="attr" name="minResizeHeight" />
+
+ <public type="attr" name="actionBarWidgetTheme" />
+
<public type="style" name="TextAppearance.SuggestionHighlight" />
<public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
<public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
@@ -1820,7 +1824,4 @@
<public type="color" name="holo_orange_dark" />
<public type="color" name="holo_purple" />
<public type="color" name="holo_blue_bright" />
-
- <public type="attr" name="minResizeWidth" />
- <public type="attr" name="minResizeHeight" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e1a31f4..d698341 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3034,6 +3034,15 @@
<!-- 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>
+ <!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+ <string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
+ <!-- Notification title when 4G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+ <string name="data_usage_4g_limit_snoozed_title">4G data limit exceeded</string>
+ <!-- Notification title when mobile data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+ <string name="data_usage_mobile_limit_snoozed_title">Mobile data limit exceeded</string>
+ <!-- Notification body when data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
+ <string name="data_usage_limit_snoozed_body"><xliff:g id="size" example="3.8GB">%s</xliff:g> over specified limit</string>
+
<!-- SSL Certificate dialogs -->
<!-- Title for an SSL Certificate dialog -->
<string name="ssl_certificate">Security certificate</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 9b6c442..5aa47b7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -423,7 +423,6 @@
<item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item>
<item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item>
<item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item>
- <item name="android:textEditSuggestionsWindowLayout">?android:attr/textEditSuggestionsWindowLayout</item>
<item name="android:textEditSuggestionItemLayout">?android:attr/textEditSuggestionItemLayout</item>
<item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item>
</style>
@@ -624,6 +623,7 @@
<item name="android:completionThreshold">2</item>
<item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
<item name="android:popupBackground">@android:drawable/spinner_dropdown_background</item>
+ <item name="textCursorDrawable">@android:drawable/text_cursor_holo_light</item>
</style>
<style name="Widget.TabWidget">
@@ -712,16 +712,6 @@
<item name="android:quickContactWindowSize">modeLarge</item>
</style>
- <style name="Widget.ActivityChooserViewButton">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:layout_gravity">center</item>
- <item name="android:background">?android:attr/selectableItemBackground</item>
- <item name="android:adjustViewBounds">true</item>
- <item name="android:scaleType">fitCenter</item>
- <item name="android:padding">@android:dimen/action_bar_icon_vertical_padding</item>
- </style>
-
<!-- Text Appearances -->
<eat-comment />
@@ -1075,14 +1065,10 @@
</style>
<!-- Style for the popup window that contains text suggestions. -->
- <style name="Widget.TextSuggestions">
- <item name="android:popupAnimationStyle">@android:style/Animation.TextSuggestions</item>
- </style>
-
- <!-- Animation effects when showing/hiding the text suggestions popup window. -->
- <style name="Animation.TextSuggestions">
- <item name="windowEnterAnimation">@android:anim/fade_in</item>
- <item name="windowExitAnimation">@android:anim/fade_out</item>
+ <style name="Widget.TextSuggestionsPopupWindow">
+ <item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
+ <item name="android:popupBackground">@android:drawable/text_edit_suggestions_window</item>
+ <item name="android:dropDownWidth">wrap_content</item>
</style>
<style name="Widget.ActionBar">
@@ -1552,7 +1538,7 @@
<style name="Widget.Holo.TextSelectHandle" parent="Widget.TextSelectHandle">
</style>
- <style name="Widget.Holo.TextSuggestions" parent="Widget.TextSuggestions">
+ <style name="Widget.Holo.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow">
</style>
<style name="Widget.Holo.AbsListView" parent="Widget.AbsListView">
@@ -1983,6 +1969,9 @@
<style name="Widget.Holo.Light.TextSelectHandle" parent="Widget.TextSelectHandle">
</style>
+ <style name="Widget.Holo.Light.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow">
+ </style>
+
<style name="Widget.Holo.Light.AbsListView" parent="Widget.AbsListView">
</style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 93ccfe3..3e7c5ca 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -189,8 +189,7 @@
<item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item>
<item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item>
<item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item>
- <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestions</item>
- <item name="textEditSuggestionsWindowLayout">@android:layout/text_edit_suggestions_window</item>
+ <item name="textSuggestionsWindowStyle">@android:style/Widget.TextSuggestionsPopupWindow</item>
<item name="textEditSuggestionItemLayout">@android:layout/text_edit_suggestion_item</item>
<item name="textCursorDrawable">@null</item>
@@ -291,6 +290,7 @@
<item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item>
<item name="actionMenuTextAppearance">@android:style/TextAppearance.Holo.Widget.ActionBar.Menu</item>
<item name="actionMenuTextColor">?android:attr/textColorPrimary</item>
+ <item name="actionBarWidgetTheme">@null</item>
<item name="dividerVertical">@drawable/divider_vertical_dark</item>
<item name="dividerHorizontal">@drawable/divider_vertical_dark</item>
@@ -954,7 +954,7 @@
<item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
<item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
- <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestions</item>
+ <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestionsPopupWindow</item>
<item name="textCursorDrawable">@android:drawable/text_cursor_holo_dark</item>
<!-- Widget styles -->
@@ -1043,6 +1043,7 @@
<item name="actionBarStyle">@android:style/Widget.Holo.ActionBar</item>
<item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@android:style/Widget.Holo.PopupWindow.ActionMode</item>
+ <item name="actionBarWidgetTheme">@null</item>
<item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_dark</item>
<item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_dark</item>
@@ -1250,7 +1251,7 @@
<item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
<item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
- <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.TextSuggestions</item>
+ <item name="textSuggestionsWindowStyle">@android:style/Widget.Holo.Light.TextSuggestionsPopupWindow</item>
<item name="textCursorDrawable">@android:drawable/text_cursor_holo_light</item>
<!-- Widget styles -->
@@ -1339,6 +1340,7 @@
<item name="actionBarStyle">@android:style/Widget.Holo.Light.ActionBar</item>
<item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@android:style/Widget.Holo.Light.PopupWindow.ActionMode</item>
+ <item name="actionBarWidgetTheme">@null</item>
<item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_light</item>
<item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_light</item>
@@ -1400,6 +1402,7 @@
<style name="Theme.Holo.Light.SolidActionBar.Inverse">
<item name="android:windowContentOverlay">@android:drawable/title_bar_shadow</item>
<item name="android:actionBarStyle">@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse</item>
+ <item name="actionBarWidgetTheme">@android:style/Theme.Holo</item>
<item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item>
<item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
diff --git a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
index bbf1696..4814c61 100644
--- a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
@@ -65,13 +65,13 @@
assertEquals(0, first.getText().size());
assertFalse(first.isChecked());
assertNull(first.getContentDescription());
- assertEquals(0, first.getItemCount());
+ assertEquals(-1, first.getItemCount());
assertEquals(AccessibilityEvent.INVALID_POSITION, first.getCurrentItemIndex());
assertFalse(first.isEnabled());
assertFalse(first.isPassword());
- assertEquals(0, first.getFromIndex());
- assertEquals(0, first.getAddedCount());
- assertEquals(0, first.getRemovedCount());
+ assertEquals(-1, first.getFromIndex());
+ assertEquals(-1, first.getAddedCount());
+ assertEquals(-1, first.getRemovedCount());
// get another event from the pool (this must be the recycled first)
AccessibilityEvent second = AccessibilityEvent.obtain();
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 0b8d40f..05bd626 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -159,6 +159,7 @@
<assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
<assign-permission name="android.permission.ACCESS_DRM" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
+ <assign-permission name="android.permission.WAKE_LOCK" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index ef1deba..dc79d95 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -13,10 +13,15 @@
<h2>In this document</h2>
-<ol> <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
-<li><a href="#manifest-filters">Filtering based on Manifest File Elements</a></li>
-<li><a href="#other-filters">Other Filters</a></li>
-<li><a href="#advanced-filters">Advanced Manifest Filters</a></li>
+<ol>
+ <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
+ <li><a href="#manifest-filters">Filtering based on Manifest Elements</a>
+ <ol>
+ <li><a href="#advanced-filters">Advanced manifest filters</a></li>
+ </ol>
+ </li>
+ <li><a href="#other-filters">Other Filters</a></li>
+ <li><a href="#MultiApks">Publishing Multiple APKs with Different Filters</a></li>
</ol>
<h2>See also</h2>
@@ -39,75 +44,72 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></code></a></li>
</ol>
-<div id="qv-extra"> <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
-<div id="qv-sub-rule"> <img src="{@docRoot}assets/images/icon_market.jpg"
-style="float:left;margin:0;padding:0;"> <p style="color:#669999;">Interested in
-publishing your app on Android Market?</p> <a id="publish-link"
-href="http://market.android.com/publish">Go to Android Market »</a> </div>
+<div id="qv-extra">
+ <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
+ <div id="qv-sub-rule">
+ <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
+ <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
+ <p><a id="publish-link"
+href="http://market.android.com/publish">Go to Android Market</a> to create a publisher
+account and upload your app.</p></div>
</div>
</div>
</div>
-<p>When a user searches or browses in Android Market, the results are filtered based on which
-applications are compatible with the user's device. For example, if an application requires a
-trackball (as specified in the manifest file), then Android Market will not show
-the app on any device that does not have a trackball.</p>
+<p>When a user searches or browses in Android Market on an Android device, the results are filtered
+based on which applications are compatible with that device. For example, if an application
+requires a camera (as specified in the application manifest file), then Android Market will not show
+the app on any device that does not have a camera.</p>
-<p>The manifest file and the device's hardware and features are only part of how applications are
-filtered—filtering might also depend on the country and carrier, the presence or absence of a
-SIM card, and other factors. </p>
+<p>Declarations in the manifest file that are compared to the device's configuration is not the
+only part of how applications are filtered. Filtering might also occur due to the user's country and
+carrier, the presence or absence of a SIM card, and other factors. </p>
-<p>Changes to the Android Market filters are independent of changes
-to the Android platform itself. This document will be updated periodically to reflect
-any changes that affect the way Android Market filters applications.</p>
+<p>Changes to the Android Market filters are independent of changes to the Android platform itself.
+This document is updated periodically to reflect any changes that affect the way Android Market
+filters applications.</p>
<h2 id="how-filters-work">How Filters Work in Android Market</h2>
<p>Android Market uses the filter restrictions described below to determine
whether to show your application to a user who is browsing or searching for
-applications on an Android-powered device. When determining whether to display your app,
-Market checks the device's hardware and software capabilities, as well as it's
+applications from the Android Market app. When determining whether to display your app,
+Market checks the device's hardware and software configuration, as well as it's
carrier, location, and other characteristics. It then compares those against the
-restrictions and dependencies expressed by the application itself, in its
+restrictions and dependencies expressed by the application's
manifest file and publishing details. If the application is
compatible with the device according to the filter rules, Market displays the
application to the user. Otherwise, Market hides your application from search
-results and category browsing. </p>
+results and category browsing, even if a user specifically requests
+the app by clicking a deep link that points directly to the app's ID within Market..</p>
-<p>You can use the filters described below to control whether Market shows or
-hides your application to users. You can use any combination of the
-available filters for your app—for example, you can set a
-<code>minSdkVersion</code> requirement of <code>"4"</code> and set
-<code>smallScreens="false"</code> in the app, then when uploading the app to
-Market you could target European countries (carriers) only. Android Market's
-filters would prevent the application from being visible on any device that did
-not match all three of these requirements. </p>
+<p class="note"><strong>Note:</strong> When users browse the <a
+href="http://market.android.com">Android Market web site</a>, they can see all published
+applications. The Android Market web site compares the application requirements to each of the
+user's registered devices for compatibility, though, and only allows them to install the application
+if it's compatible with their device.</p>
- <p>A filtered app is not visible within Market, even if a user specifically requests
-the app by clicking a deep link that points directly to the app's ID within Market.
-All filtering restrictions are associated with an application's version and can
-change between versions. For example:</p>
+<p>You can use any combination of the available filters for your app. For example, you can set a
+<code>minSdkVersion</code> requirement of <code>"4"</code> and set <code>smallScreens="false"</code>
+in the app, then when uploading the app to Market you could target European countries (carriers)
+only. Android Market's filters will thus prevent the application from being available on any device
+that does not match all three of these requirements. </p>
-<ul>
-<li>If you publish a new version of your app with stricter restrictions, the app
-will not be visible to users for whom it is filtered, even if those users were
-able see the previous version.</li>
-<li>If a user has installed your application and you publish an upgrade that
-makes the app invisible to the user, the user will not see that an upgrade is
-available. </li>
-</ul>
-
+<p>All filtering restrictions are associated with an application's version and can
+change between versions. For example, if a user has installed your application and you publish an
+update that makes the app invisible to the user, the user will not see that an update is
+available.</p>
<h2 id="manifest-filters">Filtering based on Manifest Elements</h2>
<p>Most Market filters are triggered by elements within an application's
manifest file, <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>,
-although not everything in the manifest file can trigger filtering.
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
+(although not everything in the manifest file can trigger filtering).
Table 1 lists the manifest elements that you should use to trigger Android
Market filtering, and explains how the filtering for each element works.</p>
@@ -143,29 +145,22 @@
attributes, which vary by API Level. Specifically: </p>
<ul>
-<li><p>In API level 3, the <code><supports-screens></code> element itself
+<li><p>For applications that set either the <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
+minSdkVersion</a></code> or <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
+targetSdkVersion</a></code> to 3 or lower, the <code><supports-screens></code> element itself
is undefined and no attributes are available. In this case, Market assumes that
the application is designed for normal-size screens and shows the application to
-devices that have normal or large screens. </p>
+devices that have normal or larger screens. </p>
-<p>This behavior is especially significant for applications that set their
-<code><a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">android:
-minSdkVersion</a></code> to 3 or lower, since Market will filter them from
-small-screen devices by default. Such applications can enable support for
-small-screen devices by adding a <code>android:targetSdkVersion="4"</code>
-attribute to the <code><uses-sdk></code> element in their manifest
-files. For more information, see <a
-href="{@docRoot}guide/practices/screens_support.html#strategies">Strategies for
-Legacy Applications</a>.</p></li>
-
-<li>In API Level 4, the defaults for all of the attributes is
-<code>"true"</code>. If an application does not declare a
-<code><supports-screens></code> element, Market assumes that the
-application is designed for all screen sizes and does not filter it from any
-devices. If the application does not declare one of the attributes, Market uses
-the default value of <code>"true"</code> and does not filter the app for devices
-of corresponding screen size.</li>
+<li>When the either the <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">android:
+minSdkVersion</a></code> or <code><a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
+targetSdkVersion</a></code> is set to 4 or higher, the default for all attributes is
+<code>"true"</code>. In this way, the application is considered to support all screen sizes by
+default.</li>
</ul>
<p><strong>Example 1</strong><br />
@@ -192,6 +187,7 @@
Screens</a>.</p>
</td>
</tr>
+
<tr>
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></code>
<!-- ##api level 3## --></td>
@@ -207,6 +203,7 @@
<p>For more details, see <a
href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><code><uses-configuration></code></a>.</p></td>
</tr>
+
<tr>
<td rowspan="2" valign="top" style="white-space:nowrap;"><code><a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
@@ -237,6 +234,7 @@
below.</p>
</td>
</tr>
+
<tr>
<td valign="top">OpenGL-ES
Version<br />
@@ -263,6 +261,7 @@
<p>For more details, see <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>.</p></td>
</tr>
+
<tr>
<td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library></a></code></td>
<td valign="top">Software Libraries</td>
@@ -299,6 +298,7 @@
element.</p>
</td>
</tr>
+
<tr>
<td rowspan="2" valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></code></td>
<td valign="top">Minimum Framework Version (<code>minSdkVersion</code>)</td>
@@ -324,11 +324,55 @@
</table>
+
+<h3 id="advanced-filters">Advanced manifest filters</h3>
+
+<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
+filter applications based on the advanced manifest elements in table 2.</p>
+
+<p>These manifest elements and the filtering they trigger are for exceptional use-cases
+only. These are designed for certain types of high-performance games and similar applications that
+require strict controls on application distribution. <strong>Most applications should never use
+these filters</strong>.</p>
+
+<p id="table2" class="table-caption"><strong>Table 2.</strong> Advanced manifest elements for
+Android Market filtering.</p>
+<table>
+ <tr><th>Manifest Element</th><th>Summary</th></tr>
+ <tr>
+ <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+<compatible-screens>}</a></nobr></td>
+ <td>
+ <p>Android Market filters the application if the device screen size and density does not match
+any of the screen configurations (declared by a {@code <screen>} element) in the {@code
+<compatible-screens>} element.</p>
+ <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
+this manifest element</strong>. Using this element can dramatically
+reduce the potential user base for your application, by excluding all combinations of screen size
+and density that you have not listed. You should instead use the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> manifest element (described above in <a href="#table1">table
+1</a>) to enable screen compatibility mode for screen configurations you have not accounted for
+with alternative resources.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+<supports-gl-texture>}</a></nobr></td>
+ <td>
+ <p>Android Market filters the application unless one or more of the GL texture compression
+formats supported by the application are also supported by the device. </p>
+ </td>
+ </tr>
+</table>
+
+
+
<h2 id="other-filters">Other Filters</h2>
<p>Android Market uses other application characteristics to determine whether to show or hide an application for a particular user on a given device, as described in the table below. </p>
-<p id="table2" class="table-caption"><strong>Table 2.</strong> Application and publishing
+<p id="table3" class="table-caption"><strong>Table 3.</strong> Application and publishing
characteristics that affect filtering on Market.</p>
<table> <tr>
<th>Filter Name</th> <th>How It Works</th> </tr>
@@ -365,44 +409,46 @@
+<h2 id="MultiApks">Publishing Multiple APKs with Different Filters</h2>
-<h2 id="advanced-filters">Advanced Manifest Filters</h2>
+<p>Some specific Android Market filters allow you to publish multiple APKs for the same
+application in order to provide a different APK to different device configurations. For example, if
+you're creating a video game that uses high-fidelity graphic assets, you might want to create
+two APKs that each support different texture compression formats. This way, you can reduce the
+size of the APK file by including only the textures that are required for each device
+configuration. Depending on each device's support for your texture compression formats, Android
+Market will deliver it the APK that you've declared to support that device.</p>
-<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
-filter applications based on the advanced manifest elements in table 3.</p>
+<p>Currently, Android Market allows you to publish multiple APKs for the same application only
+when each APK provides different filters based on the following configurations:</p>
+<ul>
+ <li>OpenGL texture compression formats
+ <p>By using the <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+<supports-gl-texture>}</a> element.</p>
+ </li>
+ <li>Screen size (and, optionally, screen density)
+ <p>By using the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> or <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+<compatible-screens>}</a> element.</p>
+ </li>
+ <li>API level
+ <p>By using the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code
+<uses-sdk>}</a> element.</p>
+ </li>
+</ul>
-<p>These manifest elements and the filtering they trigger are for exceptional use-cases
-only. They are designed for some types of high-performance games and similar applications that
-require strict controls on application distribution. <strong>Most applications should never use
-these filters</strong>.</p>
+<p>All other filters still work the same as usual, but these three are the only filters that can
+distinguish one APK from another within the same application listing on Android Market. For example,
+you <em>cannot</em> publish multiple APKs for the same application if the APKs differ only based on
+whether the device has a camera.</p>
-<p id="table3" class="table-caption"><strong>Table 3.</strong> Advanced manifest elements for
-Android Market filtering.</p>
-<table>
- <tr><th>Manifest Element</th><th>Summary</th></tr>
- <tr>
- <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
-<compatible-screens>}</a></nobr></td>
- <td>
- <p>Android Market filters the application if the device screen size and density does not match
-any of the screen configurations (declared by a {@code <screen>} element) in the {@code
-<compatible-screens>} element.</p>
- <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
-this manifest element</strong>. Using this element can dramatically
-reduce the potential user base for your application, by excluding all combinations of screen size
-and density that you have not listed. You should instead use the <a
-href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
-<supports-screens>}</a> manifest element (described above in <a href="#table1">table
-1</a>) to enable screen compatibility mode for screen configurations you have not accounted for
-with alternative resources.</p>
- </td>
- </tr>
- <tr>
- <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
-<supports-gl-texture>}</a></nobr></td>
- <td>
- <p>Android Market filters the application unless one or more of the GL texture compression formats supported by the application are also supported by the device. </p>
- </td>
- </tr>
-</table>
+<p class="caution"><strong>Caution:</strong> Publishing multiple APKs for the same application is
+considered an advanced feature and <strong>most application should publish only one
+APK that supports a wide range of device configurations</strong>. Publishing multiple APKs
+requires that you follow specific rules within your filters and that you pay extra attention to the
+version codes for each APK to ensure proper update paths for each configuration.</p>
+<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/developing/debugging/index.jd b/docs/html/guide/developing/debugging/index.jd
index 1f1a4ca..0ad1a08 100644
--- a/docs/html/guide/developing/debugging/index.jd
+++ b/docs/html/guide/developing/debugging/index.jd
@@ -1,4 +1,4 @@
-page.title=Debugging
+page.title=Debugging
@jd:body
@@ -10,7 +10,7 @@
<li><a href="#stack">Debugging Environment</a></li>
<li><a href="#addltools">Additional Debugging Tools</a></li>
-
+
<li><a href="#tips">Debugging Tips</a></li>
</ol>
</div>
@@ -50,7 +50,7 @@
<dd>The Dalvik VM (Virtual Machine) supports the JDWP protocol to allow debuggers to attach to
a VM. Each application runs in a VM and exposes a unique port that you can attach a debugger to
- via DDMS. If you want to debug multiple applications, attaching to each port might become
+ via DDMS. If you want to debug multiple applications, attaching to each port might become
tedious, so DDMS provides a port forwarding feature that can forward a specific VM's debugging
port to port 8700. You can switch freely from application to application by highlighting it in the
Devices tab of DDMS. DDMS forwards the appropriate port to port 8700. Most modern Java IDEs include a JDWP debugger,
@@ -109,11 +109,11 @@
that provide useful information such as CPU usage and frame rate. You can also transfer the
application to a hardware device.</dd>
</dl>
-
-
- <h2 id="tips">Debugging Tips</h2>
-
-<p>While debugging, keep these helpful tips in mind to help you figure out common problems with your
+
+
+ <h2 id="tips">Debugging Tips</h2>
+
+<p>While debugging, keep these helpful tips in mind to help you figure out common problems with your
applications:</p>
<dl>
@@ -131,14 +131,14 @@
</dd>
<dt><strong>Get application and system state information from the emulator</strong></dt>
-<dd>You can access dumpstate information from the <code>adb shell</code> commands. See
+<dd>You can access dumpstate information from the <code>adb shell</code> commands. See
<a href="{@docRoot}guide/developing/tools/adb.html#dumpsys">dumpsys and
dumpstate</a> on the adb topic page.</dd>
<dt><strong>Get wireless connectivity information</strong></dt>
-<dd>You can get information about wireless connectivity using DDMS.
+<dd>You can get information about wireless connectivity using DDMS.
From the <strong>Device</strong> menu, select <strong>Dump
radio state</strong>.</dd>
@@ -165,6 +165,16 @@
<dt><strong>Use debugging helper classes</strong></dt>
<dd>Android provides debug helper classes such as {@link android.util.Log
util.Log} and {@link android.os.Debug} for your convenience. </dd>
+
+<dt><strong>Garbage collection</strong></dt>
+<dd>
+The debugger and garbage collector are currently loosely integrated. The VM guarantees that any
+object the debugger is aware of is not garbage collected until after the debugger disconnects.
+This can result in a buildup of objects over time while the debugger is connected. For example,
+if the debugger sees a running thread, the associated {@link java.lang.Thread} object is not
+garbage collected even after the thread terminates.
+</dd>
+
</dl>
<p>See the <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting</a> document
@@ -176,10 +186,3 @@
-
-
-
-
-
-
-
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index cb5a0b6..bde170e 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -142,6 +142,9 @@
<td>Huawei</td>
<td><code>12d1</code></td></tr>
<tr>
+ <td>K-Touch</td>
+ <td><code>24e3</code></td></tr>
+ <tr>
<td>Kyocera</td>
<td><code>0482</code></td></tr>
<tr>
diff --git a/docs/html/guide/developing/index.jd b/docs/html/guide/developing/index.jd
index 3d7e353..722c75a 100644
--- a/docs/html/guide/developing/index.jd
+++ b/docs/html/guide/developing/index.jd
@@ -98,20 +98,22 @@
<dt>Jarsigner (or similar signing tool)</dt>
- <dd>To sign your .apk file with a private key generated by keytool. Jarsigner is part of the
+ <dd>To sign your .apk file with a private key generated by Keytool. Jarsigner is part of the
JDK.</dd>
</dl>
- <p>If you are using Eclipse and ADT, tools such as <code>adb</code> and the <code>android</code>
- are called by Eclipse and ADT under the hood or similar functionality is provided within Eclipse.
- You need to be familiar with <code>adb</code>, however, because certain functions are not accessible from
- Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and Jarsigner to
+ <p>If you are using Eclipse and ADT, tools such as <code>adb</code> and <code>android</code>
+ are automatically called by Eclipse and ADT so you don't have to manually invoke these tools.
+ You need to be familiar with <code>adb</code>, however, because certain functions are not
+accessible from
+ Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and
+Jarsigner to
sign your applications, but you can set up Eclipse to do this automatically as well.</p>
<p>For more information on the tools provided with the Android SDK, see the
<a href="{@docRoot}guide/developing/tools/index.html">Tools</a> section of the documentation.</p>
-<h2 id="ThirdParty">Third-Party Development Tools</h2>
+<h2 id="ThirdParty">Other Third-Party Development Tools</h2>
<p>
The tools described in this section are not developed by the Android SDK team. The Android Dev Guide
does not provide documentation for these tools. Please refer to the linked documents in each
diff --git a/docs/html/guide/developing/tools/etc1tool.jd b/docs/html/guide/developing/tools/etc1tool.jd
new file mode 100644
index 0000000..a7f76f5
--- /dev/null
+++ b/docs/html/guide/developing/tools/etc1tool.jd
@@ -0,0 +1,68 @@
+page.title=etc1tool
+parent.title=Tools
+parent.link=index.html
+@jd:body
+
+
+ <p><code>etc1tool</code> is a command line utility that lets you encode PNG
+ images to the ETC1 compression standard and decode ETC1 compressed images back to PNG.</p>
+
+ <p>The usage for <code>etc1tool</code> is:</p>
+<pre>etc1tool infile [--help | --encode | --encodeNoHeader | --decode] [--showDifference
+diff-file] [-o outfile]</pre>
+
+ <table>
+ <tr>
+ <th>Option</th>
+
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td><code>infile</code></td>
+
+ <td>The input file to compress</td>
+ </tr>
+
+ <tr>
+ <td><code>--help</code></td>
+
+ <td>Print usage information</td>
+ </tr>
+
+ <tr>
+ <td><code>--encode</code></td>
+
+ <td>Create an ETC1 file from a PNG file.
+ This is the default mode for the tool if nothing is specified.</td>
+ </tr>
+
+ <tr>
+ <td><code>--encodeNoHeader</code></td>
+
+ <td>Create a raw ETC1 data file (without a header) from a PNG file.</td>
+ </tr>
+
+ <tr>
+ <td><code>--decode</code></td>
+
+ <td>Create a PNG file from an ETC1 file</td>
+ </tr>
+
+ <tr>
+ <td><code>--showDifference <em>diff-file</em></code></td>
+
+ <td>Write the difference between the original and encoded image to
+ <code><em>diff-file</em></code> (only valid when encoding).</td>
+ </tr>
+
+ <tr>
+ <td><code>-o <em>outfile</em></code></td>
+
+ <td>Specify the name of the output file.
+ If <code><em>outfile</em></code> is not specified, the output file is constructed
+ from the input filename with the appropriate suffix (<code>.pkm</code> or <code>.png</code>).
+ </td>
+ </tr>
+
+ </table>
\ No newline at end of file
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index f7dbe30..a647cd3 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -148,7 +148,7 @@
</a></li>
</ul>
</li><!-- end of User Interface -->
-
+
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/resources/index.html">
<span class="en">Application Resources</span>
@@ -221,7 +221,7 @@
<li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html"><provider></a></li>
<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-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>
<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>
@@ -231,8 +231,8 @@
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></li>
</ul>
</li><!-- end of the manifest file -->
- </ul>
-
+ </ul>
+
<ul>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/graphics/index.html">
@@ -265,7 +265,7 @@
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/compute.html">
<span class="en">Compute</span>
</a>
- </li>
+ </li>
</ul>
</li>
@@ -383,9 +383,6 @@
<span class="en">In-app Billing</span></a>
</div>
<ul>
- <li><a href="<?cs var:toroot?>guide/market/billing/billing_about.html">
- <span class="en">About this Release</span></a>
- </li>
<li><a href="<?cs var:toroot?>guide/market/billing/billing_overview.html">
<span class="en">In-app Billing Overview</span></a>
</li>
@@ -409,6 +406,10 @@
<li><a href="<?cs var:toroot ?>guide/appendix/market-filters.html">
<span class="en">Market Filters</span></a>
</li>
+ <li><a href="<?cs var:toroot ?>guide/market/publishing/multiple-apks.html">
+ <span class="en">Multiple APK Support</span></a>
+ <span class="new">new!</span>
+ </li>
</ul>
</li>
@@ -571,8 +572,10 @@
<li><a href="<?cs var:toroot ?>guide/developing/tools/android.html">android</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a>
<li><a href="<?cs var:toroot ?>guide/developing/tools/dmtracedump.html">dmtracedump</a></li>
- <li><a href="<?cs var:toroot ?>guide/developing/tools/draw9patch.html" >Draw 9-Patch</a></li>
+ <li><a href="<?cs var:toroot?>guide/developing/tools/draw9patch.html">Draw
+ 9-Patch</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
+ <li><a href="<?cs var:toroot ?>guide/developing/tools/etc1tool.html">etc1tool</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/hprof-conv.html">hprof-conv</a></li>
<li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>
@@ -668,11 +671,14 @@
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/practices/screens_support.html">
<span class="en">Supporting Multiple Screens</span>
- </a></div>
+ </a> <span class="new">updated</span></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/practices/screens-distribution.html">
<span class="en">Distributing to Specific Screens</span>
</a></li>
+ <li><a href="<?cs var:toroot ?>guide/practices/screen-compat-mode.html">
+ <span class="en">Screen Compatibility Mode</span>
+ </a> <span class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>guide/practices/screens-support-1.5.html">
<span class="en">Strategies for Android 1.5</span>
</a></li>
@@ -727,9 +733,16 @@
<li><a href="<?cs var:toroot ?>guide/practices/design/accessibility.html">
<span class="en">Designing for Accessibility</span>
</a></li>
- <li><a href="<?cs var:toroot ?>guide/practices/design/performance.html">
+ <li class="toggle-list">
+ <div><a href="<?cs var:toroot ?>guide/practices/design/performance.html">
<span class="en">Designing for Performance</span>
- </a></li>
+ </a> <span class="new-child">new!</span></div>
+ <ul>
+ <li><a href="<?cs var:toroot ?>guide/practices/design/jni.html">
+ <span class="en">JNI Tips</span>
+ </a> <span class="new">new!</span></li>
+ </ul>
+ </li>
<li><a href="<?cs var:toroot ?>guide/practices/design/responsiveness.html">
<span class="en">Designing for Responsiveness</span>
</a></li>
diff --git a/docs/html/guide/market/billing/billing_about.html b/docs/html/guide/market/billing/billing_about.html
new file mode 100644
index 0000000..d8395df
--- /dev/null
+++ b/docs/html/guide/market/billing/billing_about.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<meta http-equiv="refresh"
+content="0;url=http://developer.android.com/guide/market/billing/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/market/billing/index.html">click
+here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/market/billing/billing_about.jd b/docs/html/guide/market/billing/billing_about.jd
deleted file mode 100755
index 5924170..0000000
--- a/docs/html/guide/market/billing/billing_about.jd
+++ /dev/null
@@ -1,30 +0,0 @@
-page.title=About this Release
-parent.title=In-app Billing
-parent.link=index.html
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
- <h2>In this document</h2>
- <ol>
- <li><a href="#billing-about">About this Release</a></li>
- </ol>
- <h2>Downloads</h2>
- <ol>
- <li><a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">Sample Application</a></li>
- </ol>
- <h2>See also</h2>
- <ol>
- <li><a href="{@docRoot}guide/market/billing/billing_overview.html">Overview of In-app Billing</a></li>
- <li><a href="{@docRoot}guide/market/billing/billing_integrate.html">Implementing In-app Billing</a></li>
- <li><a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a></li>
- <li><a href="{@docRoot}guide/market/billing/billing_testing.html">Testing In-app Billing</a></li>
- <li><a href="{@docRoot}guide/market/billing/billing_admin.html">Administering In-app Billing</a></li>
- <li><a href="{@docRoot}guide/market/billing/billing_reference.html">In-app Billing Reference</a></li>
- </ol>
-</div>
-</div>
-
-<p>Android Market In-app Billing has reached the final launch milestone and is now available to developers and users. You can now publish applications that use Android Market's in-app billing service, and users can make in-app purchases. To find out how to implement in-app billing in your applications, see the <a href="{@docRoot}guide/market/billing/index.html">documentation</a> and the <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample application</a>.</p>
-
-
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index 939bbaa..cbb4b29 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -202,6 +202,11 @@
href="http://www.google.com/support/androidmarket/bin/answer.py?answer=1153485">In-app Billing
Pricing</a>.</p>
+<p class="caution"><strong>Important:</strong> You cannot use the Google Checkout API to issue
+refunds or cancel in-app billing transactions. You must do this manually through your Google
+Checkout merchant account. However, you can use the Google Checkout API to retrieve order
+information.</p>
+
<h2 id="billing-testing-setup">Setting Up Test Accounts</h2>
<p>The Android Market publisher site lets you set up one or more test accounts. A test account is a
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index 1a1f02a..3eebd59 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -783,11 +783,17 @@
<code>RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error
information about the request.</p>
-<p class="note"><strong>Note:</strong> As a best practice, you should not send a
-<code>CONFIRM_NOTIFICATIONS</code> request for a purchased item until you have delivered the item to
-the user. This way, if your application crashes or something else prevents your application from
-delivering the product, your application will still receive an <code>IN_APP_NOTIFY</code> broadcast
-intent from Android Market indicating that you need to deliver the product.</p>
+<p>You must send a confirmation when you receive transaction information from Android Market. If you
+don't send a confirmation message, Android Market will continue sending
+<code>IN_APP_NOTIFY</code> messages for the transactions you have not confirmed. Also,
+your application must be able to handle <code>IN_APP_NOTIFY</code> messages that contain multiple
+orders.</p>
+
+<p>In addition, as a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request
+for a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+that you need to deliver the product.</p>
<h4>Restoring transaction information (RESTORE_TRANSACTIONS)</h4>
@@ -828,6 +834,10 @@
signed JSON string (unencrypted). The message includes the signature so you can verify the integrity
of the signed string.</p>
+<p class="note"><strong>Note:</strong> You should use the <code>RESTORE_TRANSACTIONS</code>
+request type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.</p>
+
<h3>Other service tasks</h3>
<p>You may also want your {@link android.app.Service} to receive intent messages from your {@link
@@ -1061,7 +1071,12 @@
Design</a>.</p>
<p class="note"><strong>Note</strong>: If you store any purchase information on a device, be sure to
-encrypt the data and use a device-specific encryption key.</p>
+encrypt the data and use a device-specific encryption key. Also, if the purchase type for any of
+your items is "unmanaged," we recommend that you back up the purchase information for these items to
+a remote server or use Android's <a href="{@docRoot}guide/topics/data/backup.html">data
+backup</a> framework to back up the purchase information. Backing up purchase information for
+unmanaged items is important because unmanaged items cannot be restored by using the
+<code>RESTORE_TRANSACTIONS</code> request type.</p>
<h3>Creating a user interface for selecting items</h3>
diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/market/billing/billing_overview.jd
index a42b772..8f9fd4c 100755
--- a/docs/html/guide/market/billing/billing_overview.jd
+++ b/docs/html/guide/market/billing/billing_overview.jd
@@ -257,7 +257,10 @@
<code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and <code>REQUEST_ID</code>. The
<code>PURCHASE_INTENT</code> key provides a {@link android.app.PendingIntent}, which your
application uses to start the checkout UI for the given product ID.</li>
- <li>Your application launches the pending intent, which launches the checkout UI.</li>
+ <li>Your application launches the pending intent, which launches the checkout UI.
+ <p class="note"><strong>Note:</strong> You must launch the pending intent from an activity
+ context and not an application context.</p>
+ </li>
<li>When the checkout flow finishes (that is, the user successfully purchases the item or cancels
the purchase), Android Market sends your application a notification message (an
<code>IN_APP_NOTIFY</code> broadcast intent). The notification message includes a notification ID,
@@ -276,14 +279,21 @@
<code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key.</li>
</ol>
-<p class="note"><strong>Note:</strong> You must launch the pending intent from an activity context
-and not an application context.</p>
-
<img src="{@docRoot}images/billing_request_purchase.png" height="231" id="figure2" />
<p class="img-caption">
<strong>Figure 2.</strong> Message sequence for a purchase request.
</p>
+<p>Keep in mind, you must send a confirmation when you receive transaction information from Android
+Market (step 8 in figure 2). If you don't send a confirmation message, Android Market will
+continue sending <code>IN_APP_NOTIFY</code> messages for the transactions you have not
+confirmed. As a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request for
+a purchased item until you have delivered the item to the user. This way, if your application
+crashes or something else prevents your application from delivering the product, your application
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+that you need to deliver the product. Also, as a best practice, your application must be able to
+handle <code>IN_APP_NOTIFY</code> messages that contain multiple orders.</p>
+
<p>The messaging sequence for a restore transaction request is shown in figure 3. Request types for
each <code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents
are shown in <em>italic</em>. For clarity, figure 3 does not show the <code>RESPONSE_CODE</code>
@@ -308,6 +318,10 @@
information that is sent during a purchase request, although you do not need to respond to this
intent with a <code>CONFIRM_NOTIFICATIONS</code> message.</p>
+<p class="note"><strong>Note:</strong> You should use the <code>RESTORE_TRANSACTIONS</code> request
+type only when your application is installed for the first time on a device or when your
+application has been removed from a device and reinstalled.</p>
+
<p>The messaging sequence for checking whether in-app billing is supported is shown in figure 4. The
request type for the <code>sendBillingRequest()</code> method is shown in <strong>bold</strong>.</p>
@@ -335,21 +349,32 @@
<code>GET_PURCHASE_INFORMATION</code> request. Android Market responds with a
<code>PURCHASE_STATE_CHANGED</code> broadcast intent, which contains the details of the purchase
state change. Your application then sends a <code>CONFIRM_NOTIFICATIONS</code> message, informing
-Android Market that you've received the purchase state change information.</p>
+Android Market that you have received the purchase state change information.</p>
-<p>When Android Market receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given message, it
-usually stops sending <code>IN_APP_NOTIFY</code> intents for that message. However, there are some
-cases where Android Market may send repeated <code>IN_APP_NOTIFY</code> intents for a message even
-though your application has sent a <code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a
-device loses network connectivity while you are sending the <code>CONFIRM_NOTIFICATIONS</code>
-message. In this case, Android Market might not receive your <code>CONFIRM_NOTIFICATIONS</code>
-message and it could send multiple <code>IN_APP_NOTIFY</code> messages until it receives
-acknowledgement that you received the message. Therefore, your application must be able to recognize
-that the subsequent <code>IN_APP_NOTIFY</code> messages are for a previously processed transaction.
-You can do this by checking the <code>orderID</code> that's contained in the JSON string because
-every transaction has a unique <code>orderId</code>.</p>
+<p>In some special cases, you may receive multiple <code>IN_APP_NOTIFY</code> messages even though
+you have confirmed receipt of the purchase information, or you may receive
+<code>IN_APP_NOTIFY</code> messages for a purchase change even though you never initiated the
+purchase. Your application must handle both of these special cases.</p>
-<p>There are two cases where your application may also receive <code>IN_APP_NOTIFY</code> broadcast
+<h4>Handling multiple IN_APP_NOTIFY messages</h4>
+
+<p>When Android Market receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given
+<code>PURCHASE_STATE_CHANGED</code> message, it usually stops sending <code>IN_APP_NOTIFY</code>
+intents for that <code>PURCHASE_STATE_CHANGED</code> message. Sometimes, however, Android
+Market may send repeated <code>IN_APP_NOTIFY</code> intents for a
+<code>PURCHASE_STATE_CHANGED</code> message even though your application has sent a
+<code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a device loses network connectivity
+while you are sending the <code>CONFIRM_NOTIFICATIONS</code> message. In this case, Android Market
+might not receive your <code>CONFIRM_NOTIFICATIONS</code> message and it could send multiple
+<code>IN_APP_NOTIFY</code> messages until it receives acknowledgement that you received the
+transaction message. Therefore, your application must be able to recognize that the subsequent
+<code>IN_APP_NOTIFY</code> messages are for a previously processed transaction. You can do this by
+checking the <code>orderID</code> that's contained in the JSON string because every transaction has
+a unique <code>orderId</code>.</p>
+
+<h4>Handling refunds and other unsolicited IN_APP_NOTIFY messages</h4>
+
+<p>There are two cases where your application may receive <code>IN_APP_NOTIFY</code> broadcast
intents even though your application has not sent a <code>REQUEST_PURCHASE</code> message. Figure 5
shows the messaging sequence for both of these cases. Request types for each
<code>sendBillingRequest()</code> method are shown in <strong>bold</strong>, broadcast intents are
@@ -359,11 +384,11 @@
<div class="figure" style="width:481px">
<img src="{@docRoot}images/billing_refund.png" alt="" height="189" />
<p class="img-caption">
- <strong>Figure 5.</strong> Message sequence for refunds and other unsolicited IN_APP_NOTIFY messages.
-</p>
+ <strong>Figure 5.</strong> Message sequence for refunds and other unsolicited
+IN_APP_NOTIFY messages.</p>
</div>
-<p>In the first case, your application can receive an <code>IN_APP_NOTIFY</code> broadcast intent
+<p>In the first case, your application may receive an <code>IN_APP_NOTIFY</code> broadcast intent
when a user has your application installed on two (or more) devices and the user makes an in-app
purchase from one of the devices. In this case, Android Market sends an <code>IN_APP_NOTIFY</code>
message to the second device, informing the application that there is a purchase state change. Your
@@ -384,6 +409,11 @@
<code>PURCHASE_STATE_CHANGED</code> broadcast intent. Also, the <code>purchaseState</code> field in
the JSON string is set to 2.</p>
+<p class="caution"><strong>Important:</strong> You cannot use the Google Checkout API to
+issue refunds or cancel in-app billing transactions. You must do this manually through your
+Google Checkout merchant account. However, you can use the Google Checkout API to retrieve order
+information.</p>
+
<h2 id="billing-security">Security Controls</h2>
<p>To help ensure the integrity of the transaction information that is sent to your application,
diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/market/billing/billing_testing.jd
index 84d25b2..5453047 100755
--- a/docs/html/guide/market/billing/billing_testing.jd
+++ b/docs/html/guide/market/billing/billing_testing.jd
@@ -211,7 +211,8 @@
users will experience in your application.</p>
<p class="note"><strong>Note</strong>: You do not need to publish your application to do end-to-end
-testing. You only need to upload your draft application to perform end-to-end testing.</p>
+testing. You only need to upload your application as a draft application to perform end-to-end
+testing.</p>
<p>To test your in-app billing implementation with actual in-app purchases, you will need to
register at least one test account on the Android Market publisher site. You cannot use your
@@ -233,8 +234,11 @@
<ol>
<li><strong>Upload your application as a draft application to the publisher site.</strong>
<p>You do not need to publish your application to perform end-to-end testing with real product
- IDs. To learn how to upload an application to Android Market, see <a
- href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
+ IDs; you only need to upload your application as a draft application. However, you must sign
+ your application with your release key before you upload it as a draft application. Also, the
+ version number of the uploaded application must match the version number of the application you
+ load to your device for testing. To learn how to upload an application to Android Market, see
+ <a href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
applications</a>.</p>
</li>
<li><strong>Add items to the application's product list.</strong>
diff --git a/docs/html/guide/market/publishing/multiple-apks.jd b/docs/html/guide/market/publishing/multiple-apks.jd
new file mode 100644
index 0000000..ff70e85
--- /dev/null
+++ b/docs/html/guide/market/publishing/multiple-apks.jd
@@ -0,0 +1,643 @@
+page.title=Multiple APK Support
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+ <h2>Quickview</h2>
+ <ul>
+ <li>Simultaneously publish different APKs for different
+device configurations</li>
+ <li>Different APKs are distributed to different devices based on filters declared in the
+manifest file</li>
+ <li>You should publish multiple APKs only when it's not possible or reasonable to
+support all desired devices with a single APK</li>
+ </ul>
+
+ <h2>In this document</h2>
+<ol>
+ <li><a href="#Concepts">Publishing Concepts</a>
+ <ol>
+ <li><a href="#Active">Active APKs</a></li>
+ <li><a href="#SimpleAndAdvanced">Simple mode and advanced mode</a></li>
+ </ol>
+ </li>
+ <li><a href="#HowItWorks">How Multiple APKs Work</a>
+ <ol>
+ <li><a href="#SupportedFilters">Supported filters</a></li>
+ <li><a href="#Rules">Rules for multiple APKs</a></li>
+ </ol>
+ </li>
+ <li><a href="#CreatingApks">Creating Multiple APKs</a>
+ <ol>
+ <li><a href="#VersionCodes">Assigning version codes</a></li>
+ </ol>
+ </li>
+ <li><a href="#SingleAPK">Using a Single APK Instead</a>
+ <ol>
+ <li><a href="#TextureOptions">Supporting multiple GL textures</a></li>
+ <li><a href="#ScreenOptions">Supporting multiple screens</a></li>
+ <li><a href="#ApiLevelOptions">Supporting multiple API levels</a></li>
+ </ol>
+ </li>
+</ol>
+
+ <h2>See also</h2>
+<ol>
+ <li><a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></li>
+ <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+ <li><a href="{@docRoot}sdk/compatibility-library.html">Compatibility
+Package</a></li>
+ <li><a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>Multiple APK support is a feature in Android Market that allows you to publish different APKs
+for your application that are each targeted to different device configurations. Each APK is a
+complete and independent version of your application, but they share the same application listing on
+Android Market and must share the same package name and be signed with the same release key. This
+feature is useful for cases in which your application cannot reach all desired devices with a single
+APK.</p>
+
+<p>Android-powered devices may differ in several ways and it's important
+to the success of your application that you make it available to as many devices as possible.
+Android applications usually run on most compatible devices with a single APK, by supplying
+alternative resources for different configurations (for example, different layouts for different
+screen sizes) and the Android system selects the appropriate resources for the device at runtime. In
+a few cases, however, a single APK is unable to support all device configurations, because
+alternative resources make the APK file too big (greater than 50MB) or other technical challenges
+prevent a single APK from working on all devices.</p>
+
+<p>Although <strong>we encourage you to develop and publish a single APK</strong> that supports as
+many device configurations as possible, doing so is sometimes not possible. To help
+you publish your application for as many devices as possible, Android Market allows you to
+publish multiple APKs under the same application listing. Android Market then supplies each APK to
+the appropriate devices based on configuration support you've declared in the manifest file of each
+APK.</p>
+
+<p>By publishing your application with multiple APKs, you can:</p>
+
+<ul>
+ <li>Support different OpenGL texture compression formats with each APK.</li>
+ <li>Support different screen configurations with each APK.</li>
+ <li>Support different platform versions with each APK.</li>
+</ul>
+
+<p>Currently, these are the only device characteristics that Android Market supports for publishing
+multiple APKs as the same application.</p>
+
+<p class="note"><strong>Note:</strong> You should generally use multiple APKs to support
+different device configurations <strong>only when your APK is too large</strong> (greater than
+50MB). Using a single APK to support different configurations is always the best practice,
+because it makes the path for application updates simple and clear for users (and also makes
+your life simpler by avoiding development and publishing complexity). Read the section below about
+<a href="#SingleAPK">Using a Single APK Instead</a> to
+consider your options before publishing multiple APKs.</p>
+
+
+<h2 id="Concepts">Publishing Concepts</h2>
+
+<p>Before you start publishing multiple APKs on Android Market, you must understand a few
+concepts regarding how the Android Market publisher site works.</p>
+
+<h3 id="Active">Active APKs</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h4>The difference between "Publish" and "Save"</h4>
+ <p>When editing your application, there are two buttons on the top-right side of the page. The
+first button is either <strong>Publish</strong> or <strong>Unpublish</strong> and the second
+button is always <strong>Save</strong> (but its behavior changes).</p>
+ <p>When your application is new or you have unpublished it from Market, the first
+button says <strong>Publish</strong>. Clicking it will publish any APKs listed as
+Active, making them available on Android Market. Also while your application is new
+or unpublished, clicking <strong>Save</strong> will save any changes you've made, such
+as information added to the Product details and APKs you've uploaded, but nothing is made visible on
+Android Market—this allows you to save your changes and sign out of the publisher site before
+deciding to publish.</p>
+ <p>Once you've published your application, the first button changes to
+<strong>Unpublish</strong>. Clicking it in this state unpublishes your application so that none
+of the APKs are available on Android Market. Also while published, the behavior of the
+<strong>Save</strong> button is different. In this state, clicking <strong>Save</strong> not
+only saves all your changes, but also publishes them to Android Market. For example, if you've
+already published your application and then make changes to your product details or activate new
+APKs, clicking <strong>Save</strong> makes all those changes live on Android Market.</p>
+</div>
+</div>
+
+
+<p>Before you can publish your application (whether publishing one or multiple APKs), you
+must "activate" your APK(s) from the <strong>APK files</strong> tab. When you activate an APK, it
+moves into the list of <em>Active</em> APKs. This list allows you to preview which APK(s)
+you're about to publish.</p>
+
+<p>If there are no errors, any "active" APK will be published to
+Android Market when you click the <strong>Publish</strong> button (if the application is
+unpublished) or when you click the <strong>Save</strong> button (if the application is
+already published).</p>
+
+
+<h3 id="SimpleAndAdvanced">Simple mode and advanced mode</h3>
+
+<p>The Android Market publisher site provides two modes for managing the APKs associated with
+your application: <em>simple mode</em> and <em>advanced mode</em>. You can switch between these by
+clicking the
+link at the top-right corner of the <strong>APK files</strong> tab.</p>
+
+<p>Simple mode is the traditional way to publish an application, using one APK at a time. In
+simple mode, only one APK can be activated at a time. If you upload a new APK to update
+the application, clicking "Activate" on the new APK deactivates the currently
+active APK (you must then click <strong>Save</strong> to publish the new APK).</p>
+
+<p>Advanced mode allows you to activate and publish multiple APKs that are each designed for a
+specific set of device configurations. However, there are several rules based on the manifest
+declarations in each APK that determine whether you're allowed to activate each APK along with
+others. When you activate an APK and it violates one of the rules, you will receive an error or
+warning message. If it's an error, you cannot publish until you resolve the problem; if it's a
+warning, you can publish the activated APKs, but there might be unintended consequences as to
+whether your application is available for different devices. These rules are discussed more
+below.</p>
+
+
+<h2 id="HowItWorks">How Multiple APKs Work</h2>
+
+<p>The concept for using multiple APKs on Android Market is that you have just one entry in
+Android Market for your application, but different devices might download a different APK. This
+means that:</p>
+
+<ul>
+ <li>You maintain only one set of product details (app description, icons, screenshots, etc.).
+This also means you <em>cannot</em> charge a different price for different APKs.</li>
+ <li>All users see only one version of your application on Android Market, so they are not
+confused by different versions you may have published that are "for tablets" or
+"for phones."</li>
+ <li>All user reviews are applied to the same application listing, even though users on different
+devices may have different APKs.</li>
+ <li>If you publish different APKs for different versions of Android (for different API levels),
+then when a user's device receives a system update that qualifies them for a different APK you've
+published, Android Market updates the user's application to the APK designed for the higher version
+of Android. Any system data associated with the application is retained (the same as with normal
+application updates when using a single APK).</li>
+</ul>
+
+<p>To publish multiple APKs for the same application, you must enable <strong>Advanced mode</strong>
+in your application's <strong>APK files</strong> tab (as discussed in the previous section). Once
+in advanced mode, you can upload, activate, then publish multiple APKs for the same application. The
+following sections describe more about how it works.</p>
+
+
+<h3 id="SupportedFilters">Supported filters</h3>
+
+<p>Which devices receive each APK is determined by <a
+href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a> that are specified by
+elements in the manifest file of each APK. However, Android Market allows you to publish multiple
+APKs only when each APK uses filters to support a variation of the following
+device characteristics:</p>
+
+<ul>
+ <li><strong>OpenGL texture compression formats</strong>
+ <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
+<supports-gl-texture>}</a> element(s).</p>
+ <p>For example, when developing a game that uses OpenGL ES, you can provide one APK for
+devices that support ATI texture compression and a separate APK for devices
+that support PowerVR compression (among many others).</p>
+ <br/>
+ </li>
+
+ <li><strong>Screen size (and, optionally, screen density)</strong>
+ <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> <em>or</em> <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+<compatible-screens>}</a> element. You should never use both elements and you should use only
+<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> when possible.</p>
+ <p>For example, you can provide one APK that supports small and normal size screens and another
+APK that supports large and xlarge screens.</p>
+
+ <p class="note"><strong>Note:</strong> The Android system provides strong support for
+applications to support all screen configurations with a single APK. You should avoid creating
+multiple APKs to support different screens unless absolutely necessary and instead follow the guide
+to <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a> so that your application is flexible and can adapt to all screen configurations
+with a single APK.</p>
+ <p class="caution"><strong>Caution:</strong> By default, all screen size attributes in the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element are "true" if you do not declare them otherwise. However,
+because the {@code android:xlargeScreens} attribute was added in Android 2.3 (API level
+9), Android Market will assume that it is "false" if your application does not set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to "9" or higher.</p>
+ <p class="caution"><strong>Caution:</strong> You should not combine both <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> and <a
+href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
+<compatible-screens>}</a> elements in your manifest file. Using both increases the chances
+that you'll introduce an error due to conflicts between them. For help deciding which to use, read
+<a href="{@docRoot}guide/practices/screens-distribution.html">Distributing to Specific Screens</a>.
+If you can't avoid using both, be aware that for any conflicts in agreement between a given size,
+"false" will win.</p>
+ <br/>
+ </li>
+
+ <li><strong>API level</strong>
+ <p>This is based on your manifest file's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a> element.
+You
+can use both the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> and <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max">{@code android:maxSdkVersion}</a>
+attributes to specify support for different API levels.</p>
+ <p>For example, you can publish your application with one APK that supports API levels 4 - 7
+(Android 1.6 - 2.1)—using only APIs available since API level 4 or lower—and another
+APK that supports API levels 8 and above (Android 2.2+)—using APIs available since API level 8
+or lower.</p>
+ <div class="note">
+ <p><strong>Note:</strong></p>
+ <ul>
+ <li>If you use this characteristic as the factor to distinguish multiple APKs, then the APK
+with a higher <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> value must have a higher <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
+value. This is also true if two APKs overlap their device support based on a different supported
+filter. This ensures that when a device receives a system update, Android Market can offer the user
+an update for your application (because updates are based on an increase in the app version code).
+This requirement is described further in the section below about <a href="#Rules">Rules for
+multiple APKs</a>.</li>
+ <li>You should avoid using <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max">{@code
+android:maxSdkVersion}</a> in general, because as long as you've properly developed your
+application with public APIs, it is always compatible with future versions of Android. If you want
+to publish a different APK for higher API levels, you still do not need to specify the
+maximum version, because if the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> is {@code "4"} in one APK and {@code "8"} in another, devices that
+support API level 8 or higher will always receive the second APK (because it's version code is
+higher, as per the previous note).</li>
+ </ul>
+ </div>
+ </li>
+</ul>
+
+<p>Other manifest elements that enable <a
+href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a>—but are not
+listed above—are still applied for each APK as usual. However, Android Market does not allow
+you to publish multiple APKs based on variations of them. Thus, you cannot publish
+multiple APKs if the above listed filters are the same for each APK (but the APKs differ based on
+other characteristics in the manifest file). For
+example, you cannot provide different APKs that differ purely on the <a
+href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">{@code
+<uses-configuration>}</a> characteristics.</p>
+
+
+
+<h3 id="Rules">Rules for multiple APKs</h3>
+
+<p>Before you enable advanced mode to publish multiple APKs for your application, you need to
+understand the following rules that define how publishing multiple APKs works:</p>
+
+<ul>
+ <li>All APKs you publish for the same application <strong>must have the same package
+name and be signed with the same certificate key</strong>.</li>
+
+ <li>Each APK <strong>must have a different version code</strong>, specified by the
+<a href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a> attribute.</li>
+
+ <li>Each APK <strong>must not exactly match the configuration support of another APK</strong>.
+ <p>That is, each APK must declare slightly different support for at least one of
+the <a href="#MarketFiltersSupported">supported Market filters</a> (listed above).</p>
+ <p>Usually, you will differentiate your APKs based on a specific characteristic (such as the
+supported texture compression formats), and thus, each APK will declare support for different
+devices. However, it's OK to publish multiple APKs that overlap their support slightly. When two
+APKs do overlap (they support some of the same device configurations), a device that falls within
+that overlap range will receive the APK with a higher version code (defined by <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a>).</p></li>
+
+ <li>You cannot activate a new APK that has a version code lower than that of the APK it's
+replacing. For example, say you have an active APK for screen sizes small - normal with version code
+0400, then try to replace it with an APK for the same screen sizes with version code 0300. This
+raises an error, because it means users of the previous APK will not be able to update the
+application.</li>
+
+ <li>An APK that requires a <strong>higher API level</strong> must have a <strong>higher
+version code</strong>.
+ <p>This is true only when either: the APKs differ based <em>only</em> on the
+supported API levels (no other <a href="#SupportedMarketFilters">supported market filters</a>
+distinguish the APKs from each other) <em>or</em> when the APKs do use another supported filter, but
+there is an overlap between the APKs within that filter.</p>
+ <p>This is important because a user's device receives an application update from
+Android Market only if the version code for the APK on Android Market is higher than the version
+code of the APK currently on the device. This ensures that if a device receives a system update that
+then qualifies it to install the APK for higher API levels, the device receives an application
+update because the version code increases.</p>
+<p class="note"><strong>Note:</strong> The size of the version code increase is irrelevant; it
+simply needs to be larger in the version that supports higher API levels.</p>
+ <p>Here are some examples:</p>
+ <ul>
+ <li>If an APK you've uploaded for API levels 4 and above (Android 1.6+) has a version code of
+{@code 0400}, then an APK for API levels 8 and above (Android 2.2+) must be {@code 0401} or
+greater. In this case, the API level is the only supported filter used, so the version codes
+<strong>must increase</strong> in correlation with the API level support for each APK, so that users
+get an update when they receive a system update.</li>
+ <li>If you have one APK that's for API level 4 (and above) <em>and</em> small -
+large screens, and another APK for API level 8 (and above) <em>and</em> large - xlarge screens, then
+the version codes <strong>must increase</strong>. In this case, the API level filter is used to
+distinguish each APK, but so is the screen size. Because the screen sizes overlap (both APKs
+support large screens), the version codes must still be in order. This ensures that a large screen
+device that receives a system update to API level 8 will receive an update for the second
+APK.</li>
+ <li>If you have one APK that's for API level 4 (and above) <em>and</em> small -
+normal screens, and another APK for API level 8 (and above) <em>and</em> large - xlarge
+screens, then the version codes <strong>do not need to increase</strong> in correlation with the API
+levels. Because there is no overlap within the screen size filter, there are no devices that
+could potentially move between these two APKs, so there's no need for the version codes to
+increase from the lower API level to the higher API level.</li>
+ </ul>
+ </li>
+
+</ul>
+
+<p>Failure to abide by the above rules results in an error on the Android Market publisher site
+when you activate your APKs—you will be unable to publish your application until you
+resolve the error.</p>
+
+<p>There are other conflicts that might occur when you activate your APKs, but which will result
+in warnings rather than errors. Warnings can be caused by the following:</p>
+
+<ul>
+ <li>When you modify an APK to "shrink" the support for a device's characteristics and no other
+APKs support the devices that then fall outside the supported range. For example, if an APK
+currently supports small and normal size screens and you change it to support only small screens,
+then you have shrunk the pool of supported devices and some devices will no longer see your
+application in Android Market. You can resolve this by adding another APK that supports normal size
+screens so that all previously-supported devices are still supported.</li>
+
+ <li>When there are "overlaps" between two or more APKs. For example, if an APK supports screen
+sizes small, normal, and large, while another APK supports sizes large and xlarge, there is an
+overlap, because both APKs support large screens. If you do not resolve this, then devices that
+qualify for both APKs (large screen devices in the example) will receive whichever APK has the
+highest version code.</li>
+</ul>
+
+<p>When such conflicts occur, you will see a warning message, but you can still publish your
+application.</p>
+
+
+
+<h2 id="CreatingApks">Creating Multiple APKs</h2>
+
+<p>Once you decide to publish multiple APKs, you probably need to create separate
+Android projects for each APK you intend to publish so that you can appropriately develop them
+separately. You can do this by simply duplicating your existing project and give it a new name.
+(Alternatively, you might use a build system that can output different resources—such
+as textures—based on the build configuration.)</p>
+
+<p class="note"><strong>Tip:</strong> One way to avoid duplicating large portions of your
+application code is to use a <a
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">library project</a>. A library
+project holds shared code and resources, which you can include in your actual application
+projects.</p>
+
+<p>When creating multiple projects for the same application, it's a good practice to identify each
+one with a name that indicates the device restrictions to be placed on the APK, so you can
+easily identify them. For example, "HelloWorld_8" might be a good name for an
+application designed for API level 8 and above.</p>
+
+<p class="note"><strong>Note:</strong> All APKs you publish for the same application
+<strong>must have the same package name and be signed with the same certificate key</strong>. Be
+sure you also understand each of the <a href="#Rules">Rules for multiple APKs</a>.</p>
+
+
+<h3 id="VersionCodes">Assigning version codes</h3>
+
+<p>Each APK for the same application <strong>must have a unique version code</strong>, specified by
+the <a href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+android:versionCode}</a> attribute. You must be careful about assigning version codes when
+publishing multiple APKs, because they must each be different, but in some
+cases, must or should be defined in a specific order, based on the configurations that each APK
+supports.</p>
+
+<h4>Ordering version codes</h4>
+
+<p>An APK that requires a higher API level must usually have a higher version code. For example, if
+you create two APKs to support different API levels, the APK for the higher API levels must have the
+higher version code. This ensures that if a device receives a system update that then qualifies it
+to install the APK for higher API levels, the user receives a notification to update the app. For
+more information about how this requirement applies, see the section above about <a
+href="#Rules">Rules for multiple APKs</a>.</p>
+
+<p>You should also consider how the order of version codes might affect which APK your users
+receive either due to overlap between coverage of different APKs or future changes you might make to
+your APKs.</p>
+
+<p>For example, if you have different APKs based on screen size, such as one for small - normal and
+one for large - xlarge, but foresee a time when you will change the APKs to be one for small and one
+for normal - xlarge, then you should make the version code for the large - xlarge APK be higher.
+That way, a normal size device will receive the appropriate update when you make the change, because
+the version code increases from the existing APK to the new APK that now supports the device. </p>
+
+<p>Also, when creating multiple APKs that differ based on support for different OpenGL texture
+compression formats, be aware that many devices support multiple formats. Because a device
+receives the APK with the highest version code when there is an overlap in coverage between two
+APKs, you should order the version codes among your APKs so that the APK with the
+preferred compression format has the highest version code. For example, you might want to perform
+separate builds for your app using PVRTC, ATITC, and ETC1 compression formats. If you prefer these
+formats in this exact order, then the APK that uses PVRTC should have the highest version code, the
+APK that uses ATITC has a lower version code, and the version with ETC1 has the lowest. Thus, if a
+device supports both PVRTC and ETC1, it receives the APK with PVRTC, because it has the highest
+version code.</p>
+
+
+<h4>Using a version code scheme</h4>
+
+<p>In order to allow different APKs to update their version codes independent of others (for
+example, when you fix a bug in only one APK, so don't need to update all APKs), you should use a
+scheme for your version codes that
+provides sufficient room between each APK so that you can increase the code in one without requiring
+an increase in others. You should also include your actual version name in the code (that is, the
+user visible version assigned to <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code android:versionName}</a>),
+so that it's easy for you to associate the version code and version name.</p>
+
+<p class="note"><strong>Note:</strong> When you increase the version code for an APK, Android
+Market will prompt users of the previous version to update the application. Thus, to avoid
+unnecessary updates, you should not increase the version code for APKs that do not actually
+include changes.</p>
+
+<p>We suggest using a version code with at least 7 digits: integers that represent
+the supported configurations are in the higher order bits, and the version name (from <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code
+android:versionName}</a>) is in the lower order bits. For example, when the application version
+name is 3.1.0, version codes for an API level 4
+APK and an API level 11 APK would be something like 0400310 and 1100310, respectively. The first
+two digits are reserved for the API Level (4 and 11, respectively), the middle two digits are for
+either screen sizes or GL texture formats (not used in these examples), and the last three digits
+are for the application's version name (3.1.0). Figure 1 shows two examples that split based on both
+the platform version (API Level) and screen size.</p>
+
+<img src="{@docRoot}images/market/version-codes.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> A suggested scheme for your version codes,
+using the first two digits for the API Level, the second and third digits for the minimum and
+maximum screen size (1 - 4 indicating each of the four sizes) or to denote the texture formats
+and the last three digits for the app version.</p>
+
+<p>This scheme for version codes is just a suggestion for how you should establish a
+pattern that is scalable as your application evolves. In particular, this scheme doesn't
+demonstrate a solution for identifying different texture compression formats. One option might be
+to define your own table that specifies a different integer to each of the different
+compression formats your application supports (for example, 1 might correspond to ETC1 and 2 is
+ATITC, and so on).</p>
+
+<p>You can use any scheme you want, but you should carefully consider how future versions of your
+application will need to increase their version codes and how devices can receive updates when
+either the device configuration changes (for example, due to a system update) or when you modify the
+configuration support for one or several of the APKs.</p>
+
+
+
+
+<h2 id="SingleAPK">Using a Single APK Instead</h2>
+
+<p><strong>Creating multiple APKs for your application is not the normal procedure</strong> for
+publishing an application on Android Market. In most cases, you should be able to publish your
+application to most users with a single APK and we encourage that you do so. When you encounter
+a situation in which using a single APK becomes difficult, you should carefully consider all your
+options before deciding to publish multiple APKs.</p>
+
+<p>First of all, there are a few key benefits to developing a single APK that supports all
+devices:</p>
+
+<ul>
+ <li><strong>Publishing and managing your application is easier.</strong>
+ <p>With only one APK to worry about at any given time, you're less likely to become confused by
+which APK is what. You also don't have to keep track of multiple version codes for each
+APK—by using only one APK, you can simply increase the version code with each release and
+be done.</p> </li>
+ <li><strong>You need to manage only a single code base.</strong>
+ <p>Although you can use a <a
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">library project</a>
+to share code between multiple Android projects, it's still likely that you'll reproduce some code
+across each project and this could become difficult to manage, especially when resolving
+bugs.</p></li>
+ <li><strong>Your application can adapt to device configuration changes.</strong>
+ <p>By creating a single APK that contains all the resources for each device configuration, your
+application can adapt to configuration changes that occur at runtime. For example, if the user docks
+or otherwise connects a handset device to a larger screen, there's a chance that this will invoke a
+system configuration change to support the larger screen. If you include all resources for different
+screen configurations in the same APK, then your application will load alternative resources and
+optimize the user experience for the new interface.</p>
+ </li>
+ <li><strong>App restore across devices just works.</strong>
+ <p>If a user has enabled data backup on his or her current device and then buys a new device
+that has a different configuration, then when the user's apps are automatically restored during
+setup, the user receives your application and it runs using the resources optimized for that device.
+For example, on a new tablet, the user receives your application and it runs with your
+tablet-optimized resources. This restore
+process does not work across different APKs, because each APK can potentially have different
+permissions that the user has not agreed to, so Android Market may not restore the application at
+all. (If you use multiple APKs, the user receives either the exact same APK if it's compatible or
+nothing at all and must manually download your application to get the APK designed for the new
+device.)</p></li>
+</ul>
+
+<p>The following sections describe some of the other options you should use to support multiple
+device configurations before deciding to publish multiple APKs.</p>
+
+
+
+<h3 id="TextureOptions">Supporting multiple GL textures</h3>
+
+<p>To support multiple types of GL textures with a single APK, your application should query the GL
+texture formats supported on the device and then use the appropriate resources or download
+them from a web server. For example, in order to keep the size of your APK small, you can query the
+device's support for different GL texture formats when the application starts for the first time and
+then download only the textures you need for that device.</p>
+
+<p>For maximum performance and compatibility, your application should use ETC1 textures wherever it
+doesn't impact the visual quality. However, because ETC1 cannot deal with images that have drastic
+chroma changes, such as line art and (most) text, and doesn't support alpha, it may not the best
+format for all textures.</p>
+
+<p>With a single APK, you should try to use ETC1 textures and uncompressed textures whenever
+reasonable, and consider the use of PVRTC, ATITC, or DXTC as a last resort when ETC1 does not
+suffice.</p>
+
+<p>Here's an example query for supported texture compression formats from inside a
+{@link android.opengl.GLSurfaceView.Renderer GLSurfaceView.Renderer}:</p>
+
+<pre>
+public void onSurfaceChanged(GL10 gl, int w, int h) {
+ String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
+ Log.d("ExampleActivity", extensions);
+}
+</pre>
+
+<p>This returns a string that lists each of the supported compression formats.</p>
+
+
+
+<h3 id="ScreenOptions">Supporting multiple screens</h3>
+
+<p>Unless your APK file exceeds the Android Market size limit of 50MB, supporting multiple screens
+should always be done with a single APK. Since Android 1.6, the Android system manages most of the
+work required for your application to run successfully on a variety of screen sizes and
+densities.</p>
+
+<p>To further optimize your application for different screen sizes and densities, you should provide
+<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
+resources</a> such as bitmap drawables at different resolutions and different layout designs for
+different screen sizes.</p>
+
+<p>For more information about how to support multiple screens with a single APK, read <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
+
+<p>Additionally, you should consider using a support library from the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Package</a> so that you can add <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> to your activity designs
+when running on larger screens such as tablets.</p>
+
+
+
+<h3 id="ApiLevelOptions">Supporting multiple API levels</h3>
+
+<p>If you want to support as many versions of the Android platform as possible, you should use
+only APIs available in the lowest reasonable version. For example, your application may not require
+APIs newer than Android 2.1 (API Level 7), which makes an application available to
+over 95% of Android-powered devices (as indicated by the <a
+href="{@docRoot}resources/dashboard/platform-versions.html">Platform Versions</a> dashboard).</p>
+
+<p>By using a support library from the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Package</a>, you can also use APIs
+from some of the latest versions (such as Android 3.0) while
+still supporting versions as low as Android 1.6. The support library includes APIs for <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a>, <a
+href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a>, and more. Using the fragment
+APIs is particularly valuable so that you can optimize your user interface for large devices such as
+tablets.</p>
+
+<p>Alternatively, if you want to use some APIs that are available only in newer versions of Android
+(which your application can still function without), then you should consider using reflection. By
+using reflection, you can check whether the current device supports certain APIs. If the APIs are
+not available, your application can gracefully disable and hide the feature.</p>
+
+<p>Another way to use new APIs only when running on a version that supports them is to check the
+API level of the current device. That is, you can query the value of {@link
+android.os.Build.VERSION#SDK_INT} and create different code paths depending on the API level
+supported by the device. For example:</p>
+
+<pre>
+if (android.os.Build.VERSION.SDK_INT >= 11) {
+ // Use APIs supported by API level 11 (Android 3.0) and up
+} else {
+ // Do something different to support older versions
+}
+</pre>
+
diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd
index 39624f5..1d0e26e 100644
--- a/docs/html/guide/practices/design/jni.jd
+++ b/docs/html/guide/practices/design/jni.jd
@@ -6,7 +6,6 @@
<h2>In this document</h2>
<ol>
- <li><a href="#what">What is JNI?</a></li>
<li><a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a></li>
<li><a href="#threads">Threads</a></li>
<li><a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a></li>
@@ -27,9 +26,6 @@
</div>
</div>
-<a name="what_is_jni" id="what_is_jni"></a>
-<h2>What is JNI?</h2>
-
<p>JNI is the Java Native Interface. It defines a way for code written in the
Java programming language to interact with native
code, e.g. functions written in C/C++. It's VM-neutral, has support for loading code from
diff --git a/docs/html/guide/practices/screen-compat-mode.jd b/docs/html/guide/practices/screen-compat-mode.jd
new file mode 100644
index 0000000..a792386
--- /dev/null
+++ b/docs/html/guide/practices/screen-compat-mode.jd
@@ -0,0 +1,257 @@
+page.title=Screen Compatibility Mode
+parent.title=Supporting Multiple Screens
+parent.link=screens_support.html
+
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+<ol>
+ <li><a href="#Disable">Disabling Screen Compatibility Mode</a></li>
+ <li><a href="#Enable">Enabling Screen Compatibility Mode</a></li>
+</ol>
+<h2>See also</h2>
+<ol>
+ <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+ <li><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a></li>
+</ol>
+</div>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-zoom.png">
+<img src="{@docRoot}images/screens_support/compat-zoom-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
+on an Android 3.2 tablet.</p>
+</div>
+
+<div class="figure" style="width:500px;">
+<a href="{@docRoot}images/screens_support/compat-stretch.png">
+<img src="{@docRoot}images/screens_support/compat-stretch-thumb.png" alt="" />
+</a>
+<p class="img-caption"><strong>Figure 2.</strong> The same application from figure 1, with
+compatibility mode disabled.</p>
+</div>
+
+<p class="caution"><strong>Notice:</strong> If you've developed an application for a version of
+Android lower than Android 3.0, but it does resize properly for larger screens such as tablets, you
+should disable screen compatibility mode in order to maintain the best user experience. To learn how
+to quickly disable the user option, jump to <a href="#Disable">Disabling Screen Compatibility
+Mode</a>.</p>
+
+<p>Screen compatibility mode is an escape hatch for applications that are not properly designed
+to resize for larger screens such as tablets. Since Android 1.6, Android has supported a
+variety of screen sizes and does most of the work to resize application layouts so that they
+properly fit each screen. However, if your application does not successfully follow the guide to
+<a href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a>,
+then it might encounter some rendering issues on larger screens. For applications with this
+problem, screen compatibility mode can make the application a little more usable on larger
+screens.</p>
+
+<p>There are two versions of screen compatibility mode with slightly different behaviors:</p>
+<dl>
+ <dt>Version 1 (Android 1.6 - 3.1)</dt>
+ <dd>The system draws the application's UI in a "postage stamp"
+window. That is, the system draws the application's layout the same as it would on a
+normal size handset (emulating a 320dp x 480dp screen), with a black border that fills
+the remaining area of the screen.
+
+<p>This was introduced with Android 1.6 to handle apps that were designed only for the
+original screen size of 320dp x 480dp. Because there are so few active devices remaining that run
+Android 1.5, almost all applications should be developed against Android 1.6 or greater and
+should not have version 1 of screen compatibility mode enabled for larger screens. This version
+is considered obsolete.</p>
+ <p>To disable this version of screen compatibility mode, you simply need to set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "4"} or higher, or set <a
+href="guide/topics/manifest/supports-screens-element.html#resizeable">{@code
+android:resizeable}</a> to {@code "true"}.</p>
+ </dd>
+
+ <dt>Version 2 (Android 3.2 and greater)</dt>
+ <dd>The system draws the application's layout the same as
+it would on a normal size handset (approximately emulating a 320dp x 480dp screen), then scales it
+up to fill the screen. This essentially "zooms" in on your layout to make it bigger,
+which will usually cause artifacts such as blurring and pixelation in your UI.
+ <p>This was introduced with Android 3.2 to further
+assist applications on the latest tablet devices when the applications have not yet
+implemented techniques for <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
+ <p>In general, large screen devices running Android 3.2 or higher allow users to enable
+screen compatibility mode when the application does not <strong>explicitly declare that it supports
+large screens</strong> in the manifest file. When this is the case, an icon (with
+outward-pointing arrows) appears next to the clock in the system bar, which allows the user to
+toggle screen compatibility mode on and off (figure 3). An application can also explicitly
+declare that it <em>does not</em> support large screens such that screen compatibility mode
+is always enabled and the user cannot disable it. (How to declare your application's
+support for large screens is discussed in the following sections.)</p></dd>
+</dl>
+
+<img src="{@docRoot}images/screens_support/compat-toggle.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> The pop up menu to toggle screen compatibility
+mode (currently disabled, so normal resizing occurs).</p>
+
+<p>As a developer, you have control over when your application uses screen compatibility mode. The
+following sections describe how you can choose to disable or enable screen compatibility mode for
+larger screens when running Android 3.2 or higher.</p>
+
+
+<h2 id="Disable">Disabling Screen Compatibility Mode</h2>
+
+<p>If you've developed your application primarily for versions of Android lower than 3.0, but
+<strong>your application does resize properly</strong> for larger screens such as tablets,
+<strong>you should disable screen compatibility mode</strong> in order to maintain the best user
+experience. Otherwise, users may enable screen compatibility mode and experience your application in
+a less-than-ideal format.</p>
+
+<p>By default, screen compatibility mode for devices running Android 3.2 and higher is offered to
+users as an optional feature when one of the following is true:</p>
+
+<ul>
+ <li>Your application has set both <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "10"} or lower and <strong>does not explicitly
+declare support</strong> for large screens using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element.</li>
+
+ <li>Your application has set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher and <strong>explicitly declares that it does
+not support</strong> large screens, using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element.</li>
+</ul>
+
+<p>To completely disable the user option for screen compatibility mode and remove the icon in the
+system bar, you can do one of the following:</p>
+
+<ul>
+ <li><strong>Easiest:</strong>
+ <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#xlarge">{@code
+android:xlargeScreens}</a> attribute to {@code "true"}:</p>
+<pre>
+<supports-screens android:xlargeScreens="true" />
+</pre>
+ <p>That's it. This declares that your application supports all larger screen sizes, so the
+system will always resize your layout to fit the screen. This works regardless of what values
+you've set in the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a>
+attributes.</p>
+ </li>
+
+ <li><strong>Easy but has other effects:</strong>
+ <p>In your manifest's <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a>
+element, set <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher:</p>
+<pre>
+<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" />
+</pre>
+ <p>This declares that your application supports Android 3.0 and, thus, is designed to
+work on larger screens such as tablets.</p>
+ <p class="caution"><strong>Caution:</strong> When running on Android 3.0 and greater, this also
+has the effect of enabling the Holographic theme for you UI, adding the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> to your activities, and removing the
+Options Menu button in the system bar.</p>
+ <p>If screen compatibility mode is still enabled after you change this, check your manifest's <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> and be sure that there are no attributes set {@code "false"}. The best
+practice is to always explicitly declare your support for different screen sizes using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element, so you should use this element anyway.</p>
+ <p>For more information about updating your application to target Android 3.0 devices, read <a
+href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android
+3.0</a>.</p>
+ </li>
+<!--
+ <li><strong>Most control</strong> (but you must compile against Android 3.2 or higher):
+ <p>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element and specify the {@code android:compatibleWidthLimitDp}
+attribute to any value <em>higher than</em> {@code "320"}:</p>
+<pre>
+<supports-screens android:compatibleWidthLimitDp="720" />
+</pre>
+ <p>Using this technique allows you to specify exactly what your application's limit is for
+layout resizing. Normally, only applications that are already built against Android 3.2 (or
+higher) use this attribute, because the primary intention is to specify at what size should screen
+compatibility mode actually be offered to users.</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 to any device if
+your value for {@code android:compatibleWidthLimitDp} is larger than 320.</p>
+ </li>
+ -->
+</ul>
+
+
+
+<h2 id="Enable">Enabling Screen Compatibility Mode</h2>
+
+<p>When your application is targeting Android 3.2 (API level 13) or higher, you can affect
+whether compatibility mode is enabled for certain screens by using the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element.</p>
+
+<p class="note"><strong>Note:</strong> Screen compatibility mode is <strong>not</strong> a mode in
+which you should want your application to run—it causes pixelation and blurring in your UI,
+due to zooming. The proper way to make your application work well on large screens is to follow the
+guide to <a
+href="{@docRoot}guide/topics/practices/screens_support.html">Supporting Multiple Screens</a> and
+provide alternative layouts for different screen sizes.</p>
+
+<p>By default, when you've set either <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+android:minSdkVersion}</a> or <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+android:targetSdkVersion}</a> to {@code "11"} or higher, screen compatibility mode is
+<strong>not</strong> available to users. If either of these are true and your application does not
+resize properly for larger screens, you can choose to enable screen compatibility mode in one
+of the following ways:</p>
+
+<ul>
+ <li>In your manifest file, add the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element and specify the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> attribute to {@code "320"}:</p>
+<pre>
+<supports-screens android:compatibleWidthLimitDp="320" />
+</pre>
+ <p>This indicates that the maximum "smallest screen width" for which your application is designed
+is 320dp. This way, any devices with their smallest side being larger than this value will offer
+screen compatibility mode as a user-optional feature.</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 to any device if
+your value for <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> is larger than 320.</p>
+ </li>
+
+ <li>If your application is functionally broken when resized for large screens and you want to
+force users into screen compatibility mode (rather than simply providing the option), you can use
+the <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">{@code
+android:largestWidthLimitDp}</a> attribute:
+<pre>
+<supports-screens android:largestWidthLimitDp="320" />
+</pre>
+ <p>This works the same as <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">{@code
+android:compatibleWidthLimitDp}</a> except it force-enables
+screen compatibility mode and does not allow users to disable it.</p>
+ </li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd
index 0c5193b..951e364cc 100644
--- a/docs/html/guide/practices/screens-distribution.jd
+++ b/docs/html/guide/practices/screens-distribution.jd
@@ -17,6 +17,7 @@
<ol>
<li><a href="#FilteringHansetApps">Filtering a Handset Application from Tablets</a></li>
<li><a href="#FilteringTabletApps">Filtering a Tablet Application from Handsets</a></li>
+ <li><a href="#MultiApks">Publishing Multiple APKs for Different Screens</a></li>
</ol>
<h2>See also</h2>
@@ -43,7 +44,7 @@
should understand the techniques for <a
href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and implement
them to the best of your ability. By supporting multiple screens, your application can be made
-available to the greatest number of users with different devices, using a single {@code .apk}.</p>
+available to the greatest number of users with different devices, using a single APK.</p>
@@ -144,9 +145,9 @@
with <em>larger</em> screens) and set the larger screen size attributes to {@code "false"}, then
external services such as Android Market <strong>do not</strong> apply filtering. Your application
will still be available to larger screens, but when it runs, it will not resize to fit the screen.
-Instead, the system will draw it in a "postage stamp" window that's the same relative size as the
-screen size that your application does support (see <a
-href="screens-support-1.5.html#CompatMode">compatibility mode</a> for more information). If you want
+Instead, the system will emulate a handset screen size (about 320dp x 480dp; see <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">Screen Compatibility Mode</a> for more
+information). If you want
to prevent your application from being downloaded on larger screens, use <a
href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
<compatible-screens>}</a>, as discussed in the previous section about <a
@@ -162,3 +163,24 @@
or you have decided to provide different versions of your application for different sets of screen
configurations.</p>
+
+
+<h2 id="MultiApks">Publishing Multiple APKs for Different Screens</h2>
+
+<p>Although we recommend that you publish one APK for your application, Android Market allows
+you to publish multiple APKs for the same
+application when each APK supports a different set of screen configurations (as declared in
+the manifest file). For example, if you want to publish both a handset version and a tablet
+version of your application, but you're unable to make the same APK work for both screen sizes,
+you can actually publish two APKs for the same application listing. Depending on each device's
+screen configuration, Android Market will deliver it the APK that you've declared to support that
+device's screen.</p>
+
+<p>Beware, however, that publishing multiple APKs for the same application is
+considered an advanced feature and <strong>most applications should publish only one
+APK that can support a wide range of device configurations</strong>. Supporting multiple screen
+sizes, especially, is within reason using a single APK, as long as you follow the guide to
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
+
+<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/practices/screens-support-1.5.jd b/docs/html/guide/practices/screens-support-1.5.jd
index 6fd36bb..9f033b4 100644
--- a/docs/html/guide/practices/screens-support-1.5.jd
+++ b/docs/html/guide/practices/screens-support-1.5.jd
@@ -18,7 +18,6 @@
<h2>In this document</h2>
<ol>
<li><a href="#strategies">Adding Multiple Screens Support</a></li>
- <li><a href="#CompatMode">Compatibility Mode</a></li>
</ol>
<h2>See also</h2>
@@ -47,11 +46,13 @@
default, an application written for Android 1.5 or below that does not set the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
android:targetSdkVersion}</a> set to {@code "4"} or higher runs in <a
-href="#CompatMode">compatibility mode</a> when on a device with a screen larger than the
+href="screen-compat-mode">screen compatibility mode</a> when on a device with a screen larger than
+the
<em>normal</em> screen size (basically, the system displays the application in a small window
that is roughly the size of the normal screen size).</p>
-<p>This document describes how to get your application out of <a href="#CompatMode">compatibility
+<p>This document describes how to get your application out of <a
+href="screen-compat-mode.html">screen compatibility
mode</a> and instead support multiple screens, but also maintain compatibility with Android 1.5 and
below.</p>
@@ -144,43 +145,3 @@
href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to add
complete support for different screen configurations.</p>
-
-<h2 id="CompatMode">Compatibility Mode</h2>
-
-<div class="figure" style="width:450px;margin:0">
-<img src="{@docRoot}images/screens_support/compat-mode-on.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> An application running in compatibility mode
-on an extra large screen.</p>
-</div>
-
-<p>To allow applications to run on larger screens without stretching the UI, Android provides a
-compatibility mode that draws an application's UI in a "postage stamp" window when on larger
-screens. That is, the system displays the application at the baseline size (<em>normal</em>) and
-density (<em>mdpi</em>), with a black border that fills the rest of the screen.</p>
-
-<p>Compatibility mode exists primarily to support application's developed for Android 1.5 (or lower)
-when running on larger screens, because multiple screen support was not added until Android 1.6,
-older applications were not designed to support different screen configurations.</p>
-
-<p>As such, if you've set your <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> to {@code "3"} or lower and have <em>not</em> set the <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher, then compatibility mode is enabled and
-the system will not scale your application, because your application implicitly declares that it
-only supports the baseline screen configuration (normal screen size and medium density).</p>
-
-<p>To disable compatibility mode, set either <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-android:minSdkVersion}</a> or <a
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-android:targetSdkVersion}</a> to {@code "4"} or higher. For more information, see the previous
-section about <a href="#strategies">Adding Multiple Screens Support</a>.</p>
-
-<p>You can also affect whether compatibility mode is enabled by using the <a
-href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
-<supports-screens>}</a> element (you can enable it by setting {@code android:resizeable} or
-specific screen sizes to {@code "false"}). However, you should not explicitly enable compatibility
-mode for your application, but should instead apply the necessary techniques to <a
-href="{@docRoot}guide/practices/screens_support.html">supporting multiple screens</a> and allow your
-application to properly fit the screen on all screen sizes.</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 14de152..6dec4b3 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -25,6 +25,13 @@
<li><a href="#qualifiers">Using configuration qualifiers</a></li>
<li><a href="#DesigningResources">Designing alternative layouts and drawables</a></li>
</ol></li>
+ <li><a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> <span
+class="new">new!</span>
+ <ol>
+ <li><a href="#NewQualifiers">Using new size qualifiers</a></li>
+ <li><a href="#ConfigurationExamples">Configuration examples</a></li>
+ <li><a href="#DeclaringScreenSizeSupport">Declaring screen size support</a></li>
+ </ol></li>
<li><a href="#screen-independence">Best Practices</a></li>
<li><a href="#DensityConsiderations">Additional Density Considerations</a>
<ol>
@@ -57,15 +64,15 @@
applications, the Android system provides a consistent development environment across devices and
handles most of the work to adjust each application's user interface to the screen on which it is
displayed. At the same time, the system provides APIs that allow you to control your
-application's UI on specific screen sizes and densities, in order to modify and optimize your UI
+application's UI for specific screen sizes and densities, in order to optimize your UI
design for different screen configurations. For example, you might want a UI for tablets
-that's different from the design for handsets.</p>
+that's different from the UI for handsets.</p>
-<p>Although the system performs sufficient scaling and resizing to make your application work on
+<p>Although the system performs scaling and resizing to make your application work on
different screens, you should make the effort to optimize your application for different screen
sizes and densities. In doing so, you maximize the user experience for all devices and your users
believe that your application was actually designed for <em>their</em> devices—rather than
-simply stretched to fit their devices.</p>
+simply stretched to fit the screen on their devices.</p>
<p>By following the practices described in this document, you can create an application that
displays properly and provides an optimized user experience on all supported screen configurations,
@@ -74,7 +81,14 @@
<p class="note"><strong>Note:</strong> The information in this document assumes that your
application is designed for Android 1.6 (API Level 4) or higher. If your application supports
Android 1.5 or lower, please first read <a
-href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.</p>
+href="{@docRoot}guide/practices/screens-support-1.5.html">Strategies for Android 1.5</a>.
+<br/><br/>
+Also, be aware that <strong>Android 3.2 has introduced new APIs</strong> that allow you to more
+precisely control the layout resources your application uses for different screen sizes. These new
+features are especially important if you're developing an application that's optimized for tablets.
+For details, see the section about <a href="#DeclaringTabletLayouts">Declaring Tablet Layouts for
+Android 3.2</a>.
+</p>
@@ -143,9 +157,16 @@
<li>A set of four generalized <strong>sizes</strong>: <em>small</em>, <em>normal</em>,
<em>large</em>,
and <em>xlarge</em></em>
+<p class="note"><strong>Note:</strong> Beginning with Android 3.2 (API level 13), these size groups
+are deprecated in favor of a new technique for managing screen sizes based on the available screen
+width. If you're developing for Android 3.2 and greater, see <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for more
+information.</p>
+</li>
<li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
(medium),
<em>hdpi</em> (high), and <em>xhdpi</em> (extra high)
+</li>
</ul>
<p>The generalized sizes and densities are arranged around a
@@ -154,7 +175,7 @@
G1, which has an HVGA screen (until Android 1.6, this was the only screen configuration that Android
supported).</p>
-<p>Each generalized size or density spans a range of actual screen sizes or density. For example,
+<p>Each generalized size and density spans a range of actual screen sizes and densities. For example,
two devices that both report a screen size of <em>normal</em> might have actual screen sizes and
aspect ratios that are slightly different when measured by hand. Similarly, two devices that report
a screen density of <em>hdpi</em> might have real pixel densities that are slightly different.
@@ -168,11 +189,30 @@
Illustration of how Android roughly maps actual sizes and densities
to generalized sizes and densities (figures are not exact).</p>
+<p>As you design your UI for different screen sizes, you'll discover that each design requires a
+minimum amount of space. So, each generalized screen size above has an associated minimum
+resolution that's defined by the system. These minimum sizes are in "dp" units—the same units
+you should use when defining your layouts—which allows the system to avoid worrying about
+changes in screen density.</p>
+
+<ul>
+ <li><em>xlarge</em> screens are at least 960dp x 720dp</li>
+ <li><em>large</em> screens are at least 640dp x 480dp</li>
+ <li><em>normal</em> screens are at least 470dp x 320dp</li>
+ <li><em>small</em> screens are at least 426dp x 320dp</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> These minimum screen sizes were not as well defined prior to
+Android 3.0, so you may encounter some devices that are mis-classified between normal and large.
+These are also based on the physical resolution of the screen, so may vary across devices—for
+example a 1024x720 tablet with a system bar actually has a bit less space available to the
+application due to it being used by the system bar.</p>
+
<p>To optimize your application's UI for the different screen sizes and densities, you can provide
<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
resources</a> for any of the generalized sizes and densities. Typically, you should
provide alternative layouts for some of the different screen sizes and alternative bitmap images for
-different screen densities. At runtime, the system uses the appropriate size or density resources
+different screen densities. At runtime, the system uses the appropriate resources
for your application, based on the generalized size or density of the current device screen.</p>
<p>You do not need to provide alternative resources for every combination of screen size and
@@ -221,7 +261,7 @@
</ul>
<p>In figure 2, the text view and bitmap drawable have dimensions specified in pixels ({@code px}
-units), so the elements are physically larger on a low density screen and smaller on a high density
+units), so the views are physically larger on a low density screen and smaller on a high density
screen. This is because although the actual screen sizes may be the same, the high density screen
has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout
dimensions are specified in density-independent pixels ({@code dp} units). Because the baseline for
@@ -255,6 +295,18 @@
however, you should also:</p>
<ul>
+ <li><strong>Explicitly declare in the manifest which screen sizes your application
+supports</strong>
+ <p>By declaring which screen sizes your application supports, you can ensure that only
+devices with the screens you support can download your application. Declaring support for
+different screen sizes can also affect how the system draws your application on larger
+screens—specifically, whether your application runs in <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a>.</p>
+ <p>To declare the screen sizes your application supports, you should include the
+<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
+<supports-screens>}</a> element in your manifest file.</p>
+ </li>
+
<li><strong>Provide different layouts for different screen sizes</strong>
<p>By default, Android resizes your application layout to fit the current device screen. In most
cases, this works fine. In other cases, your UI might not look as good and might need adjustments
@@ -264,6 +316,12 @@
<p>The configuration qualifiers you can use to provide size-specific resources are
<code>small</code>, <code>normal</code>, <code>large</code>, and <code>xlarge</code>. For
example, layouts for an extra large screen should go in {@code layout-xlarge/}.</p>
+ <p>Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you
+should instead use the {@code sw<N>dp} configuration qualifier to define the smallest
+available width required by your layout resources. For example, if your multi-pane tablet layout
+requires at least 600dp of screen width, you should place it in {@code layout-sw600dp/}. Using the
+new techniques for declaring layout resources is discussed further in the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>.</p>
</li>
<li><strong>Provide different bitmap drawables for different screen densities</strong>
@@ -386,7 +444,7 @@
</tr>
<tr>
-<td rowspan="5">Density</td>
+<td rowspan="6">Density</td>
<td><code>ldpi</code></td>
<td>Resources for low-density (<em>ldpi</em>) screens (~120dpi).</td>
</tr>
@@ -408,7 +466,15 @@
<td>Resources for all densities. These are density-independent resources. The system does not
scale resources tagged with this qualifier, regardless of the current screen's density.</td>
</tr>
-
+<tr>
+<td><code>tvdpi</code></td>
+<td>Resources for screens somewhere between mdpi and hdpi; approximately 213dpi. This is not
+considered a "primary" density group. It is mostly intended for televisions and most apps shouldn't
+need it—providing mdpi and hdpi resources is sufficient for most apps and the system will
+scale them as appropriate. If you find it necessary to provide tvdpi resources, you should size them
+at a factor of 1.33*mdpi. For example, a 100px x 100px image for mdpi screens should be 133px x
+133px for tvdpi.</td>
+</tr>
<tr>
<td rowspan="2">Orientation</td>
<td><code>land</code></td>
@@ -432,6 +498,12 @@
</tr>
</table>
+<p class="note"><strong>Note:</strong> If you're developing your application for Android 3.2 and
+higher, see the section about <a
+href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for information about
+new configuration qualifiers that you should use when declaring layout resources for specific
+screen sizes (instead of using the size qualifiers in table 1).</p></p>
+
<p>For more information about how these qualifiers roughly correspond to real screen
sizes and densities, see <a href="#range">Range of Screens Supported</a>, earlier in this
document.</p>
@@ -457,6 +529,20 @@
<a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
Providing Alternative Resources</a>.</p>
+<p>Be aware that, when the Android system picks which resources to use at runtime, it uses
+certain logic to determing the "best matching" resources. That is, the qualifiers you use don't
+have to exactly match the current screen configuration in all cases in order for the system to
+use them. Specifically, when selecting resources based on the size qualifiers, the system will
+use resources designed for a screen smaller than the current screen if there are no resources
+that better match (for example, a large-size screen will use normal-size screen resources if
+necessary). However, if the only available resources are <em>larger</em> than the current screen,
+the system will not use them and your application will crash if no other resources match the device
+configuration (for example, if all layout resources are tagged with the {@code xlarge} qualifier,
+but the device is a normal-size screen). For more information about how the system selects
+resources, read <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">How Android Finds the
+Best-matching Resource</a>.</p>
+
<p class="note"><strong>Tip:</strong> If you have some drawable resources that the system
should never scale (perhaps because you perform some adjustments to the image yourself at
runtime), you should place them in a directory with the {@code nodpi} configuration qualifier.
@@ -554,6 +640,291 @@
+
+<h2 id="DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</h2>
+
+<p>For the first generation of tablets running Android 3.0, the proper way to declare tablet
+layouts was to put them in a directory with the {@code xlarge} configuration qualifier (for example,
+ {@code res/layout-xlarge/}). In order to accommodate other types of tablets and screen
+sizes—in particular, 7" tablets—Android 3.2 introduces a new way to specify resources
+for more discrete screen sizes. The new technique is based on the amount of space your layout needs
+(such as 600dp of width), rather than trying to make your layout fit the generalized size groups
+(such as <em>large</em> or <em>xlarge</em>).</p>
+
+<p>The reason designing for 7" tablets is tricky when using the generalized size groups is
+that a 7" tablet is technically in the same group as a 5" handset (the <em>large</em> group). While
+these two devices are seemingly close to each other in size, the amount of space for an
+application's UI is significantly different, as is the style of user interaction. Thus, a 7" and 5"
+screen should not always use the same layout. To make it possible for you to provide different
+layouts for these two kinds of screens, Android now allows you to specify your layout resources
+based on the width and/or height that's actually available for your application's layout, specified
+in dp units.</p>
+
+<p>For example, after you've designed the layout you want to use for tablet-style devices, you might
+determine that the layout stops working well when the screen is less than 600dp wide. This threshold
+thus becomes the minimum size that you require for your tablet layout. As
+such, you can now specify that these layout resources should be used only when there is at least
+600dp of width available for your application's UI.</p>
+
+<p>You should either pick a width and design to it as your minimum size, or test what is the
+smallest width your layout supports once it's complete.</p>
+
+<p class="note"><strong>Note:</strong> Remember that all the figures used with these new size APIs
+are density-indpendent pixel (dp) values and your layout dimensions should also always be defined
+using dp units, because what you care about is the amount of screen space available after the system
+accounts for screen density (as opposed to using raw pixel resolution). For more information about
+density-indpendent pixels, read <a href="#terms">Terms and concepts</a>, earlier in this
+document.</p>
+
+
+<h3 id="NewQualifiers">Using new size qualifiers</h3>
+
+<p>The different resource configurations that you can specify based on the space available for your
+layout are summarized in table 2. These new qualifiers offer you more control over the specific
+screen sizes your application supports, compared to the traditional screen size groups (small,
+normal, large, and xlarge).</p>
+
+<p class="note"><strong>Note:</strong> The sizes that you specify using these qualifiers are
+<strong>not the actual screen sizes</strong>. Rather, the sizes are for the width or height in dp
+units that are <strong>available to your activity's window</strong>. The Android system
+might use some of the screen for system UI (such as the system bar at the bottom of the screen or
+the status bar at the top), so some of the screen might not be available for your layout. Thus, the
+sizes you declare should be specifically about the sizes needed by your activity—the system
+accounts for any space used by system UI when declaring how much space it provides for your layout.
+Also beware that the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> is considered
+a part of your application's window space, although your layout does not declare it, so it reduces
+the space available for your layout and you must account for it in your design.</p>
+
+<p class="table-caption"><strong>Table 2.</strong> New configuration qualifers for screen size
+(introduced in Android 3.2).</p>
+<table>
+ <tr><th>Screen configuration</th><th>Qualifier values</th><th>Description</th></tr>
+ <tr><td>smallestWidth</td>
+ <td><code>sw<N>dp</code><br/><br/>
+ Examples:<br/>
+ <code>sw600dp</code><br/>
+ <code>sw720dp</code><br/>
+ </td>
+ <td>
+ <p>The fundamental size of a screen, as indicated by the shortest dimension of the available
+screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
+height and width (you may also think of it as the "smallest possible width" for the screen). You can
+use this qualifier to ensure that, regardless of the screen's current orientation, your
+application's has at least {@code <N>} dps of width available for it UI.</p>
+ <p>For example, if your layout requires that its smallest dimension of screen area be at
+least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
+available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
+height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
+device's smallestWidth does not change when the screen's orientation changes</strong>.</p>
+ <p>The smallestWidth of a device takes into account screen decorations and system UI. For
+example, if the device has some persistent UI elements on the screen that account for space along
+the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual
+screen size, because those are screen pixels not available for your UI.</p>
+ <p>This is an alternative to the generalized screen size qualifiers (small, normal, large, xlarge)
+that allows you to define a discrete number for the effective size available for your UI.
+Using smallestWidth to determine the general screen size is useful because width is
+often the driving factor in designing a layout. A UI will often scroll vertically, but have fairly
+hard constraints on the minimum space it needs horizontally. The available width is also the key
+factor in determining whether to use a one-pane layout for handsets or multi-pane layout for
+tablets. Thus, you likely care most about what the smallest possible width will be on each
+device.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>Available screen width</td>
+ <td><code>w<N>dp</code><br/><br/>
+ Examples:<br/>
+ <code>w720dp</code><br/>
+ <code>w1024dp</code><br/>
+ </td>
+ <td>
+ <p>Specifies a minimum available width in dp units at which the resources should be
+used—defined by the <code><N></code> value. The system's corresponding value for the
+width changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual width that's available for your UI.</p>
+ <p>This is often useful to determine whether to use a multi-pane layout, because even on a
+tablet device, you often won't want the same multi-pane layout for portrait orientation as you do
+for landscape. Thus, you can use this to specify the minimum width required for the layout, instead
+of using both the screen size and orientation qualifiers together.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>Available screen height</td>
+ <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 resources should be
+used—defined by the <code><N></code> value. The system's corresponding value for
+the height changes when the screen's orientation switches between landscape and portrait to
+reflect the current actual height that's available for your UI.</p>
+ <p>Using this to define the
+height required by your layout is useful in the same way as <code>w<N>dp</code> is for
+defining the required width, instead of using both the screen size and orientation qualifiers.
+However, most apps won't need this qualifier, considering that UIs often scroll vertically and are
+thus more flexible with how much height is available, whereas the width is more rigid.</p>
+ </td>
+ </tr>
+</table>
+
+<p>While using these qualifiers might seem more complicated than using screen size groups, it should
+actually be simpler once you determine the requirements for your UI. When you design your UI,
+the main thing you probably care about is the actual size at which your application switches between
+a handset-style UI and a tablet-style UI that uses multiple panes. The exact point of this switch
+will depend on your particular design—maybe you need a 720dp width for your tablet layout,
+maybe 600dp is enough, or 480dp, or some number between these. Using these qualifiers in table 2,
+you are in control of the precise size at which your layout changes.</p>
+
+<p>For more discussion about these size configuration qualifiers, see the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+Providing Resources</a> document.</p>
+
+
+<h3 id="ConfigurationExamples">Configuration examples</h3>
+
+<p>To help you target some of your designs for different types of devices, here are some
+numbers for typical screen widths:</p>
+
+<ul>
+ <li>320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).</li>
+ <li>480dp: a tweener tablet like the Streak (480x800 mdpi).</li>
+ <li>600dp: a 7” tablet (600x1024 mdpi).</li>
+ <li>720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).</li>
+</ul>
+
+<p>Using the size qualifiers from table 2, your application can switch between your different layout
+resources for handsets and tablets using any number you want for width and/or height. For example,
+if 600dp is the smallest available width supported by your tablet layout, you can provide these two
+sets of layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets
+res/layout-sw600dp/main_activity.xml # For tablets
+</pre>
+
+<p>In this case, the smallest width of the available screen space must be 600dp in order for the
+tablet layout to be applied.</p>
+
+<p>For other cases in which you want to further customize your UI to differentiate between sizes
+such as 7” and 10” tablets, you can define additional smallest width layouts:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets (smaller than 600dp available width)
+res/layout-sw600dp/main_activity.xml # For 7” tablets (600dp wide and bigger)
+res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)
+</pre>
+
+<p>Notice that the previous two sets of example resources use the "smallest width" qualifer, {@code
+sw<N>dp}, which specifies the smallest of the screen's two sides, regardless of the
+device's current orientation. Thus, using {@code sw<N>dp} is a simple way to specify the
+overall screen size available for your layout by ignoring the screen's orientation.</p>
+
+<p>However, in some cases, what might be
+important for your layout is exactly how much width or height is <em>currently</em> available. For
+example, if you have a two-pane layout with two fragments side by side, you might want to use it
+whenever the screen provides at least 600dp of width, whether the device is in landscape or
+portrait orientation. In this case, your resources might look like this:</p>
+
+<pre class="classic">
+res/layout/main_activity.xml # For handsets (smaller than 600dp available width)
+res/layout-w600dp/main_activity.xml # Multi-pane (any screen with 600dp available width or more)
+</pre>
+
+<p>Notice that the second set is using the "available width" qualifier, {@code w<N>dp}. This
+way, one device may actually use both layouts, depending on the orientation of the screen (if
+the available width is at least 600dp in one orientation and less than 600dp in the other
+orientation).</p>
+
+<p>If the available height is a concern for you, then you can do the same using the {@code
+h<N>dp} qualifier. Or, even combine the {@code w<N>dp} and {@code h<N>dp}
+qualifiers if you need to be really specific.</p>
+
+
+<h3 id="DeclaringScreenSizeSupport">Declaring screen size support</h3>
+
+<p>Once you've implemented your layouts for different screen sizes, it's equally important that you
+declare in your manifest file which screens your application supports.</p>
+
+<p>Along with the new configuration qualifiers for screen size, Android 3.2 introduces new
+attributes for the <a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens></a>
+manifest element:</p>
+
+<dl>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">
+{@code android:requiresSmallestWidthDp}</a></dt>
+ <dd>Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of
+the screen space (in {@code dp} units) that must be available to your application UI—that is,
+the shortest of the available screen's two dimensions. So, in order for a device to be considered
+compatible with your application, the device's smallestWidth must be equal to or greater than this
+value. (Usually, the value you supply for this is the "smallest width" that your layout supports,
+regardless of the screen's current orientation.)
+ <p>For example, if your application is only for tablet-style devices with a 600dp
+smallest available width:</p>
+<pre>
+<manifest ... >
+ <supports-screens android:requiresSmallestWidthDp="600" />
+ ...
+</manifest>
+</pre>
+ <p>However, if your application supports all screen sizes supported by Android (as small as
+426dp x 320dp), then you don't need to declare this attribute, because the smallest width your
+application requires is the smallest possible on any device.</p>
+
+ <p class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
+attribute, so it does not affect how your application behaves at runtime. Instead, it is used
+to enable filtering for your application on services such as Android Market. However,
+<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+3.2), so you should continue using the other size attributes if your application does not support
+small screens.</p>
+</dd>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#compatibleWidth">
+{@code android:compatibleWidthLimitDp}</a></dt>
+ <dd>This attribute allows you to enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> as a
+user-optional feature by specifying the maximum "smallest width" that your application
+supports. If the smallest side of a device's available screen is greater than your value here,
+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 users to toggle screen compatibility
+mode on and off.
+ <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute. We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+
+ <dt><a
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#largestWidth">
+{@code android:largestWidthLimitDp}</a></dt>
+ <dd>This attribute allows you to force-enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> by specifying
+the maximum "smallest width" that your application supports. If the smallest
+side of a device's available screen is greater than your value here, the application runs in screen
+compatibility mode with no way for the user to disable it.
+ <p class="note"><strong>Note:</strong> If your application's layout properly resizes for large
+screens, you do not need to use this attribute. We recommend that you avoid using this
+attribute and instead ensure your layout resizes for larger screens by following the
+recommendations in this document.</p></dd>
+</dl>
+
+<p class="caution"><strong>Caution:</strong> When developing for Android 3.2 and higher, you
+should not use the older screen size attributes in combination with the attributes
+listed above. Using both the new attributes and the older size attributes might cause
+unexpected behavior.</p>
+
+<p>For more information about each of these attributes, follow the respective links above.</p>
+
+
+
+
<h2 id="screen-independence">Best Practices</h2>
<p>The objective of supporting multiple screens is to create an application that can function
@@ -875,7 +1246,7 @@
the {@code <sdk>/tools/} directory (on all platforms). Figure 6 shows the Android SDK and
AVD Manager with a selection of AVDs, for testing various screen configurations.</p>
-<p>Table 2 shows the various emulator skins that are available in the Android SDK, which you can use
+<p>Table 3 shows the various emulator skins that are available in the Android SDK, which you can use
to emulate some of the most common screen configurations.</p>
<p>For more information about creating and using AVDs to test your application, see <a
@@ -883,7 +1254,7 @@
Manager</a>.</p>
-<p class="table-caption" id="screens-table"><strong>Table 2.</strong> Various screen
+<p class="table-caption" id="screens-table"><strong>Table 3.</strong> Various screen
configurations available from emulator skins in the Android SDK (indicated in bold) and other
representative resolutions.</p>
diff --git a/docs/html/guide/publishing/preparing.jd b/docs/html/guide/publishing/preparing.jd
index f471961..69aecd4 100644
--- a/docs/html/guide/publishing/preparing.jd
+++ b/docs/html/guide/publishing/preparing.jd
@@ -78,9 +78,6 @@
and performance. However, we strongly recommend that you test your application
on an actual target device before publishing it. </li>
-<li>If you are targeting the <a href="http://www.t-mobileg1.com/">T-Mobile
-G1</a> device for your application, make sure that your UI handles screen
-orientation changes. </li>
</ul>
<h3 id="eula">2. Consider adding an End User License Agreement in your
diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd
index 95d89fa..fa677e6 100644
--- a/docs/html/guide/publishing/publishing.jd
+++ b/docs/html/guide/publishing/publishing.jd
@@ -39,7 +39,7 @@
<div id="qv-extra">
<img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
<div id="qv-sub-rule">
- <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;">
+ <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
<h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
<p><a href="http://market.android.com/publish">Go to Android Market</a> to
create a developer account and upload your application. For more information about the
@@ -155,48 +155,43 @@
<p>To help users discover your published applications, you can use two special Android Market URIs
that direct users to your application's details page or perform a search for all of your published
-applications in Android Market. You can use these URIs to do the following:</p>
+applications in Android Market. You can use these URIs to create a button in your application or a
+link on a web page that:</p>
<ul>
- <li>Create a button in your application or a link on a web page that opens one of your
-application's details page in the Android Market application or web site.</li>
- <li>Create a button in your application or a link on a web page that searches for all your
-published applications in the Android Market application or web site.</li>
+ <li>Opens your application's details page in the Android Market application or web site.</li>
+ <li>Searches for all your published applications in the Android Market application or web
+site.</li>
</ul>
<p>You can launch the Android Market application or web site in the following ways:</p>
<ul>
<li>Initiate an {@link android.content.Intent} from your application that launches the
-Android Market application on the user's device. The intent must use the {@link
-android.content.Intent#ACTION_VIEW} action, and include intent data with the appropriate
-Android Market URI scheme.</li>
- <li>Provide a hyperlink on a web page that opens the Android Market web site.</li>
+Android Market application on the user's device.</li>
+ <li>Provide a link on a web page that opens the Android Market web site (but will also
+open the Android Market application if clicked from a device).</li>
</ul>
-<p>In both cases, you need to create a URI that indicates either the application you'd like to view
-in Android Market or the search you'd like to perform. The URI is quite similar whether you want
-to open the application or open the web site. The only difference is the URI prefix.</p>
+<p>In both cases, whether you want to initiate the action from your application or from a web
+page, the URIs are quite similar. The only difference is the URI prefix.</p>
-<p>To open the Android Market application on the device, the prefix for the intent's data URI
-is:</p>
+<p>To open the Android Market application from your application, the prefix for the intent's data
+URI is:</p>
<p style="margin-left:2em"><code>market://</code></p>
-<p>To open the Android Market web site, the prefix for the link URI is:</p>
+<p>To open Android Market from your web site, the prefix for the link URI is:</p>
<p style="margin-left:2em"><code>http://market.android.com/</code></p>
-<p>To complete each URI, you must append a string that specifies either the
-application for which you want to view or the search to execute. The following sections
-describe how to create a complete URI for each case.</p>
+<p>The following sections describe how to create a complete URI for each action.</p>
-<p class="note"><strong>Note:</strong> If you create a link to open the Android Market web site and
-the user selects it from an Android-powered device, the Android Market application will also resolve
-the link so the user can use the native application instead of the web site. Also, because the
-Android Market application also reads the {@code http://} URIs, you can also use them in an intent,
-but you should usually use the {@code market://} URIs for an intent, so that the native application
-is opened by default. You should use {@code http://} URIs only when creating links from a web
-page.</p>
+<p class="note"><strong>Note:</strong> If you create a link to open Android Market from your web
+site and the user selects it from an Android-powered device, the device's Market application will
+resolve the link so the user can use the Market application instead of opening the web
+site. As such, you should always use {@code http://market.android.com/} URIs when creating a link on
+a web page. When pointing to your apps from within your Android app, use the
+{@code market://} URIs in an intent, so that the Market application always opens.</p>
<h3 id="OpeningDetails">Opening an app's details page</h3>
@@ -209,22 +204,23 @@
<p style="margin-left:2em"><code><URI_prefix><b>details?id=</b><package_name></code></p>
-<p>The <code><package_name></code> is a placeholder for the target application's fully
-qualified package name, as declared in the <a
+<p>The <code><package_name></code> is a placeholder for the target application's
+fully-qualified package name, as declared in the <a
href="{@docRoot}guide/topics/manifest/manifest-element.html#package">{@code
package}</a> attribute of the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code
-<manifest>}</a> element in the application's manifest file.</p>
+<manifest>}</a> element.</p>
-<h4>Opening details in the Android Market application</h4>
+<h4>Opening the app details page from your Android app</h4>
-<p>To open the details page in the Android Market application, create an intent with the
-{@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p>
+<p>To open the Android Market details page from your application,
+create an intent with the {@link android.content.Intent#ACTION_VIEW} action and include a data URI
+in this format:</p>
<p style="margin-left:2em"><code>market://details?id=<package_name></code></p>
-<p>For example, here's how you can create an intent and open an application's details page in the
-Android Market application:</p>
+<p>For example, here's how you can create an intent and open an application's details page in
+Android Market:</p>
<pre>
Intent intent = new Intent(Intent.ACTION_VIEW);
@@ -232,23 +228,30 @@
startActivity(intent);
</pre>
+<p>This will open the Android Market application on the device to view the {@code
+com.android.example} application.</p>
-<h4>Opening details on the Android Market web site</h4>
-<p>To open the details page on the Android Market web site, create a link with a URI in this
+<h4>Opening the app details page from a web site</h4>
+
+<p>To open the details page from your web site, create a link with a URI in this
format:</p>
<p style="margin-left:2em">
<code>http://market.android.com/details?id=<package_name></code>
</p>
-<p>For example, here's a link that opens an application's details page on the Android Market web
-site:</p>
+<p>For example, here's a link that opens an application's details page on Android Market:</p>
<pre>
<a href="http://market.android.com/details?id=com.android.example">App Link</a>
</pre>
+<p>When clicked from a desktop web browser, this opens the Android Market web site to view the
+{@code com.android.example} application. When clicked from an Android-powered device, users are
+given the option to use either their web browser or the Android Market application to view the
+application.</p>
+
<h3 id="PerformingSearch">Performing a search</h3>
@@ -274,9 +277,9 @@
</ul>
-<h4>Searching the Android Market application</h4>
+<h4>Searching from your Android app</h4>
-<p>To perform a search in the Android Market application, create an intent with the
+<p>To initiate a search on Android Market from your application, create an intent with the
{@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p>
<p style="margin-left:2em"><code>market://search?q=<query></code></p>
@@ -292,13 +295,13 @@
startActivity(intent);
</pre>
-<p>The search result shows all applications published by the publisher and which are compatible with
-the current device.</p>
+<p>This opens the Android Market application to perform the search. The search result shows all
+applications published by the publisher that are compatible with the current device.</p>
-<h4>Searching the Android Market web site</h4>
+<h4>Searching from a web site</h4>
-<p>To perform a search on the Android Market web site, create a link with a URI in this
+<p>To initiate a search on Android Market from your web site, create a link with a URI in this
format:</p>
<p style="margin-left:2em">
@@ -307,26 +310,31 @@
<p>The query may include the {@code pub:} parameter described above.</p>
-<p>For example, here's a link that initiates a search on the Android Market web site, based on the
+<p>For example, here's a link that initiates a search on Android Market, based on the
publisher name:</p>
<pre>
<a href="http://market.android.com/search?q=pub:Your Publisher Name">Search Link</a>
</pre>
-<p>The search result shows all applications published by the publisher.</p>
+<p>When clicked from a desktop web browser, this opens the Android Market web site and performs the
+search. When clicked from an Android-powered device, users are given the option to use either their
+web browser or the Android Market application to perform the search.</p>
<h3 id="BuildaButton">Build an Android Market button</h3>
-<p>Use the following form to input either your application's package name or your publisher name
-and generate a button that you can use on your web site. The button will take users to Android
-Market to view your application details or view a list of all applications you've published.</p>
+<p>Use the following form to generate an "Available in Android Market" button that you can use on
+your web site. Input either your application's package name or publisher name and the button will
+take users to Android Market to either view your application's information or view a list of
+your published apps. If users click the button while on an Android-powered device, the Android
+Market application will respond to show users your application(s).</p>
-<p>This form offers four versions of the official "Available in Android Market" badge at
-recommended sizes. If you would like to create a different size, you can download an EPS file for
-the badges from the <a href="http://www.android.com/branding.html">Android Brand Guidelines</a>.</p>
+<p>This form offers four versions of the official "Available in Android Market" button at
+recommended sizes. If you want to create a different size, you can download an EPS file for
+the button images from the <a href="http://www.android.com/branding.html">Android Brand
+Guidelines</a>.</p>
<style type="text/css">
@@ -548,4 +556,3 @@
</tr>
</table>
-
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index 31e7c4b..e7a07e0 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -12,28 +12,33 @@
<ol>
<li><a href="#how">How property animation works</a></li>
</ol>
- </li>
+ </li>
- <li><a href="#value-animator">Animating with ValueAnimator</a></li>
+ <li><a href="#value-animator">Animating with ValueAnimator</a></li>
- <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
+ <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
- <li><a href="#choreography">Choreographing Multiple Animations with
- AnimatorSet</a></li>
-
- <li><a href="#listeners">Animation Listeners</a></li>
+ <li><a href="#choreography">Choreographing Multiple Animations with
+ AnimatorSet</a></li>
- <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
+ <li><a href="#listeners">Animation Listeners</a></li>
- <li><a href="#interpolators">Using Interpolators</a></li>
+ <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
- <li><a href="#keyframes">Specifying Keyframes</a></li>
- <li><a href="#layout">Animating Layout Changes to ViewGroups</a></li>
+ <li><a href="#interpolators">Using Interpolators</a></li>
- <li><a href="#views">Animating Views</a></li>
+ <li><a href="#keyframes">Specifying Keyframes</a></li>
- <li><a href="#declaring-xml">Declaring Animations in XML</a></li>
- </ol>
+ <li><a href="#layout">Animating Layout Changes to ViewGroups</a></li>
+
+ <li><a href="#views">Animating Views</a>
+ <ol>
+ <li><a href="#view-prop-animator">ViewPropertyAnimator</a></li>
+ </ol>
+ </li>
+
+ <li><a href="#declaring-xml">Declaring Animations in XML</a></li>
+ </ol>
<h2>Key classes</h2>
@@ -63,13 +68,13 @@
You can define an animation to change any object property over time, regardless of whether it
draws to the screen or not.The property animation system also has a few advantages over the view
animation system, which makes it more flexible to use.</p>
-
+
<p>The view animation system provides the capability to only animate View objects, so if
you wanted to animate non-View objects, you had to implement your own code to do so. The view
animation system also was constrained in the fact that it only exposed a few aspects of a View
object to animate, such as the scaling and rotation of a View but not the background color for
instance.</p>
-
+
<p>Another disadvantage of the view animation system is that it only modified where the
View was drawn, and not the actual View itself. For instance, if you animated a button to move
across the screen, the button draws correctly, but the actual location where you can click the
@@ -80,7 +85,7 @@
<p>The view animation system, however, takes less time to setup and requires less code to write.
If view animation accomplishes everything that you need to do, or if your existing code already
works the way you want, there is no need to use the property animation system.</p>
-
+
<p class="note"><strong>Tip:</strong> To see how the ADT layout editor allows you to develop and
preview animations in your layout, watch the <a
href="http://www.youtube.com/watch?v=Oq05KqjXTvs&feature=player_detailpage#t=1709s">Android
@@ -114,7 +119,7 @@
default is set to refresh every 10 ms, but the speed in which your application can refresh frames is
ultimately dependent on how busy the system is overall and how fast the system can service the underlying timer.</li>
</ul>
-
+
<h3 id="how">How the property animation system works</h3>
@@ -254,7 +259,7 @@
</tr>
</table>
-
+
<p>Evaluators tell the property animation system how to calculate values for a given
property. They take the timing data that is provided by an {@link android.animation.Animator}
class, the animation's start and end value, and calculate the animated values of the property
@@ -299,9 +304,9 @@
information on how to write a custom evaluator.</td>
</tr>
</table>
-
-
-
+
+
+
<p>A time interpolator defines how specific values in an animation are calculated as a
function of time. For example, you can specify animations to happen linearly across the whole
@@ -397,7 +402,7 @@
<pre>
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
-animation.start();
+animation.start();
</pre>
<p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
@@ -408,7 +413,7 @@
<pre>
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
-animation.start();
+animation.start();
</pre>
<p>In this code, the {@link android.animation.ValueAnimator} starts calculating the values of the
@@ -483,7 +488,7 @@
<li>Depending on what property or object you are animating, you might need to call the {@link
android.view.View#invalidate invalidate()} method on a View force the screen to redraw itself with the
- updated animated values. You do this in the
+ updated animated values. You do this in the
{@link android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate onAnimationUpdate()}
callback. For example, animating the color property of a Drawable object only cause updates to the
screen when that object redraws itself. All of the property setters on View, such as
@@ -492,7 +497,7 @@
methods with new values. For more information on listeners, see the section about <a href="#listeners">Animation Listeners</a>.
</li>
</ul>
-
+
<h2 id="choreography">Choreographing Multiple Animations with AnimatorSet</h2>
<p>In many cases, you want to play an animation that depends on when another animation starts or
@@ -576,12 +581,12 @@
{@link android.view.View#invalidate invalidate()} on a View to force that area of the
screen to redraw itself with the new animated values. For example, animating the
color property of a Drawable object only cause updates to the screen when that object
- redraws itself. All of the property setters on View,
+ redraws itself. All of the property setters on View,
such as {@link android.view.View#setAlpha setAlpha()} and
{@link android.view.View#setTranslationX setTranslationX()} invalidate the View
properly, so you do not need to invalidate the View when calling these methods with new values.
</p>
-
+
</li>
</ul>
</li>
@@ -658,7 +663,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
- android:animateLayoutChanges="true" />
+ android:animateLayoutChanges="true" />
</pre>
<p>Setting this attribute to true automatically animates Views that are added or removed from the
@@ -872,16 +877,55 @@
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
</pre>
-For more information on creating animators, see the sections on animating with
-<a href="#value-animator">ValueAnimator</a> and <a href="#object-animator">ObjectAnimator</a>
+<p>For more information on creating animators, see the sections on animating with
+<a href="#value-animator">ValueAnimator</a> and <a href="#object-animator">ObjectAnimator</a>.
+</p>
+<h3 id="view-prop-animator">Animating with ViewPropertyAnimator</h3>
+<p>The {@link android.view.ViewPropertyAnimator} provides a simple way to animate several
+properties of a {@link android.view.View} in parallel, using a single underlying {@link
+android.animation.Animator}
+object. It behaves much like an {@link android.animation.ObjectAnimator}, because it modifies the
+actual values of the view's properties, but is more efficient when animating many properties at
+once. In addition, the code for using the {@link android.view.ViewPropertyAnimator} is much
+more concise and easier to read. The following code snippets show the differences in using multiple
+{@link android.animation.ObjectAnimator} objects, a single
+{@link android.animation.ObjectAnimator}, and the {@link android.view.ViewPropertyAnimator} when
+simultaneously animating the <code>x</code> and <code>y</code> property of a view.</p>
+
+<p><strong>Multiple ObjectAnimator objects</strong></p>
+<pre>
+ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
+ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
+AnimatorSet animSetXY = new AnimatorSet();
+animSetXY.playTogether(animX, animY);
+animSetXY.start();
+</pre>
+
+<p><strong>One ObjectAnimator</strong></p>
+<pre>
+PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
+PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
+ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
+</pre>
+
+<p><strong>ViewPropertyAnimator</strong></p>
+<pre>
+myView.animate().x(50f).y(100f);
+</pre>
+
+<p>
+For more detailed information about {@link
+android.view.ViewPropertyAnimator}, see the corresponding Android Developers
+<a href="http://android-developers.blogspot.com/2011/05/introducing-viewpropertyanimator.html">blog
+post</a>.</p>
<h2 id="declaring-xml">Declaring Animations in XML</h2>
<p>The property animation system lets you declare property animations with XML instead of doing
it programmatically. By defining your animations in XML, you can easily reuse your animations
in multiple activities and more easily edit the animation sequence.</p>
-
+
<p>To distinguish animation files that use the new property animation APIs from those that use the
legacy <a href="{@docRoot}guide/topics/graphics/view-animation.html">view animation</a> framework,
starting with Android 3.1, you should save the XML files for property animations in the {@code
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 743832c..b2a78fe 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -28,7 +28,9 @@
android:<a href="#proc">process</a>="<i>string</i>"
android:<a href="#screen">screenOrientation</a>=["unspecified" | "user" | "behind" |
"landscape" | "portrait" |
- "sensor" | "nosensor"]
+ "reverseLandscape" | "reversePortrait" |
+ "sensorLandscape" | "sensorPortrait" |
+ "sensor" | "fullSensor" | "nosensor"]
android:<a href="#state">stateNotNeeded</a>=["true" | "false"]
android:<a href="#aff">taskAffinity</a>="<i>string</i>"
android:<a href="#theme">theme</a>="<i>resource or theme</i>"
@@ -589,12 +591,6 @@
uses, and therefore the choices made in specific contexts, may differ
from device to device.</td>
</tr><tr>
- <td>"{@code landscape}"</td>
- <td>Landscape orientation (the display is wider than it is tall).</td>
-</tr><tr>
- <td>"{@code portrait}"</td>
- <td>Portrait orientation (the display is taller than it is wide).</td>
-</tr><tr>
<td>"{@code user}"</td>
<td>The user's current preferred orientation.</td>
</tr><tr>
@@ -602,16 +598,47 @@
<td>The same orientation as the activity that's immediately beneath it in
the activity stack.</td>
</tr><tr>
+ <td>"{@code landscape}"</td>
+ <td>Landscape orientation (the display is wider than it is tall).</td>
+</tr><tr>
+ <td>"{@code portrait}"</td>
+ <td>Portrait orientation (the display is taller than it is wide).</td>
+</tr><tr>
+ <td>"{@code reverseLandscape}"</td>
+ <td>Landscape orientation in the opposite direction from normal landscape.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+ <td>"{@code reversePortrait}"</td>
+ <td>Portrait orientation in the opposite direction from normal portrait.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+ <td>"{@code sensorLandscape}"</td>
+ <td>Landscape orientation, but can be either normal or reverse landscape based on the device
+sensor.
+<em>Added in API level 9.</em></td>
+</tr><tr>
+ <td>"{@code sensorPortrait}"</td>
+ <td>Portrait orientation, but can be either normal or reverse portrait based on the device
+sensor.
+<em>Added in API level 9.</em></td>
+</tr><tr>
<td>"{@code sensor}"</td>
- <td>The orientation determined by a physical orientation sensor. The
- orientation of the display depends on how the user is holding the device;
- it changes when the user rotates the device.</td>
+ <td>The orientation is determined by the device orientation sensor. The orientation of the
+display depends on how the user is holding the device; it changes when the user rotates the
+device. Some devices, though, will not rotate to all four possible orientations, by default. To
+allow all four orientations, use {@code "fullSensor"}.</td>
+</tr><tr>
+ <td>"{@code fullSensor}"</td>
+ <td>The orientation is determined by the device orientation sensor for any of the 4 orientations.
+This is similar to {@code "sensor"} except this allows any of the 4 possible screen orientations,
+regardless of what the device will normally do (for example, some devices won't normally use reverse
+portrait or reverse landscape, but this enables those). <em>Added in API level 9.</em></td>
</tr><tr>
<td>"{@code nosensor}"</td>
- <td>An orientation determined without reference to a physical orientation sensor.
- The sensor is ignored, so the display will not rotate based on how the user
- moves the device. Except for this distinction, the system chooses the
- orientation using the same policy as for the "{@code unspecified}" setting.</td>
+ <td>The orientation is determined without reference to a physical orientation sensor. The sensor
+is ignored, so the display will not rotate based on how the user moves the device. Except for this
+distinction, the system chooses the orientation using the same policy as for the "{@code
+unspecified}" setting.</td>
</tr>
</table></dd>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 605a2bb..81d6e27 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,15 +8,15 @@
<dt>syntax:</dt>
<dd>
<pre class="stx">
-<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"]
+<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"]
android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
- android:<a href="#any">anyDensity</a>=["true" | "false"] />
+ android:<a href="#any">anyDensity</a>=["true" | "false"]
+ 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>"/>
</pre>
</dd>
@@ -24,37 +24,38 @@
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
<dt>description:</dt>
-<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.
+<dd>Lets you specify the screen sizes your application supports and enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> for screens
+larger than what your application supports. It's important that you always use this element in your
+application to specify the screen sizes your application supports.
<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. 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 to fit the current screen, you can
-optimize your UI for different screen sizes by providing <a
+Normal resizing applied by the system 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. However, it's
+often important that you optimize your application's 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>
+layout resources</a>. For instance, you might want to modify the layout of an activity
+when it is on a tablet compared to when running on a handset device.</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>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 ("zoomed") to fit
+larger screens using the system's <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a>. When you
+have not designed for larger screen sizes and the normal resizing does not achieve the appropriate
+results, screen compatibility mode will scale your UI by emulating a <em>normal</em> size
+screen and medium density, then zooming in so that it fills the entire screen. Beware that this
+causes pixelation and blurring of your UI, so it's better if you optimize your UI for large
+screens.</p>
+
+<p class="note"><strong>Note:</strong> Android 3.2 introduces new attributes: {@code
+android:requiresSmallestWidthDp}, {@code android:compatibleWidthLimitDp}, and {@code
+android:largestWidthLimitDp}. If you're developing your application for Android 3.2 and higher,
+you should use these attributes to declare your screen size support, instead of the attributes
+based on generalized screen sizes.</p>
<p>For more information about how to properly support different screen sizes so that you can avoid
-using screen compatibility mode, read
+using screen compatibility mode with your application, read
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
@@ -62,17 +63,90 @@
<dd>
<dl class="attr">
+
+ <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 set false, the system will run your application in <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> on large
+screens.</p>
+
+ <p><strong>This attribute is deprecated</strong>. It was introduced to help applications
+transition from Android 1.5 to 1.6, when support for multiple screens was first introduced. You
+should not use it.</p>
+ </dd>
+
+ <dt><a name="small"></a>{@code android:smallScreens}</dt>
+ <dd>Indicates whether the application supports smaller screen form-factors.
+ A small screen is defined as one with a smaller aspect ratio than
+ the "normal" (traditional HVGA) screen. An application that does
+ not support small screens <em>will not be available</em> for
+ small screen devices from external services (such as Android Market), because there is little
+the platform can do to make such an application work on a smaller screen. This is {@code "true"} by
+default.
+ </dd>
+
+ <dt><a name="normal"></a>{@code android:normalScreens}</dt>
+ <dd>Indicates whether an application supports the "normal" screen
+ form-factors. Traditionally this is an HVGA medium density
+ screen, but WQVGA low density and WVGA high density are also
+ considered to be normal. This attribute is "true" by default.
+ </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" 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.
+ <p>The default value for this actually varies between some versions, so it's better if
+you explicitly declare this attribute at all times. Beware that setting it "false" will
+generally enable <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen
+compatibility mode</a>.</p>
+ </dd>
+
+ <dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
+ <dd>Indicates whether the application supports extra large screen form-factors.
+ An xlarge screen is defined as a screen that is significantly larger
+ than a "large" screen, such as a tablet (or something larger) and may require 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.
+ <p>The default value for this actually varies between some versions, so it's better if
+you explicitly declare this attribute at all times. Beware that setting it "false" will
+generally enable <a href="{@docRoot}guide/practices/screen-compat-mode.html">screen
+compatibility mode</a>.</p>
+ <p>This attribute was introduced in API level 9.</p>
+ </dd>
+
+ <dt><a name="any"></a>{@code android:anyDensity}</dt>
+ <dd>Indicates whether the application includes resources to accommodate any screen
+ density.
+ <p>For applications that support Android 1.6 (API level 4) and higher, this is "true"
+by default and <strong>you should not set it "false"</strong> unless you're absolutely certain that
+it's necessary for your application to work. The only time it might be necessary to disable this
+is if your app directly manipulates bitmaps (see the <a
+href="{@docRoot}guide/practices/screens_support.html#DensityConsiderations">Supporting Multiple
+Screens</a> document for more information).</p>
+ </dd>
<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>
+ <dd>Specifies the minimum smallestWidth required. The smallestWidth is the shortest dimension of
+the screen space (in {@code dp} units) that must be available to your application UI—that is,
+the shortest of the available screen's two dimensions. So, in order for a device to be considered
+compatible with your application, the device's smallestWidth must be equal to or greater than this
+value. (Usually, the value you supply for this is the "smallest width" that your layout supports,
+regardless of the screen's current orientation.)
+
+ <p>For example, a typical handset screen has a smallestWidth of 320dp, a 7" tablet has a
+smallestWidth of 600dp, and a 10" tablet has a smallestWidth of 720dp. These values are generally
+the smallestWidth because they are the shortest dimension of the screen's available space.</p>
+
+<p>The size 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 display, the system declares
+the device's smallestWidth 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 minimum width required by your layout, regardless of the screen's current
+orientation.</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
@@ -80,12 +154,14 @@
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 class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
+attribute, so it does not affect how your application behaves at runtime. Instead, it is used
+to enable filtering for your application on services such as Android Market. However,
+<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+3.2), so you should continue using the other size attributes if your application does not support
+small screens.</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
@@ -95,29 +171,32 @@
<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.
+ <dd>This attribute allows you to enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> as a
+user-optional feature by specifying the maximum "smallest screen width" for which your application
+is designed. If the smallest side of a device's available screen is greater than your value here,
+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
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode emulates only 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
+ <dd>This attribute allows you to force-enable <a
+href="{@docRoot}guide/practices/screen-compat-mode.html">screen compatibility mode</a> by specifying
+the maximum "smallest screen width" for which your application is designed. If the smallest side of
+a device's available screen is greater than your value here, 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
@@ -125,102 +204,11 @@
{@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
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode emulates only 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
-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. Otherwise, it is false by default. If set false, the system will not resize
-your application when run on <em>large</em> or <em>xlarge</em> screens. Instead, the
-application appears in a "postage stamp" that equals the <em>normal</em> screen size that your
-application does support. This is less than an ideal experience for users, because the
-application appears smaller than the available screen, but it might help your application run
-normally if it were designed only for the <em>normal</em> screen size and some behaviors do not work
-when resized.</p>
- <p>To provide the best experience on all screen sizes, you should allow resizing and, if your
-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>
-
-
- <dt><a name="small"></a>{@code android:smallScreens}</dt>
- <dd>Indicates whether the application supports smaller screen form-factors.
- A small screen is defined as one with a smaller aspect ratio than
- the "normal" (traditional HVGA) screen. An application that does
- not support small screens <em>will not be available</em> for
- small screen devices from external services (such as Android Market), because there is little
-the platform can do
- to make such an application work on a smaller screen. If the application has 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,
-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>
- <dd>Indicates whether an application supports the "normal" screen
- form-factors. Traditionally this is an HVGA medium density
- 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" 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
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
-{@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>
- <dd>Indicates whether the application supports extra large screen form-factors.
- An xlarge screen is defined as a screen that is significantly larger
- than a "large" screen, such as a tablet (or something larger) and may require 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
-href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> to
-{@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><strong>This attribute is deprecated</strong> as of API level 13.</p>
- </dd>
-
- <dt><a name="any"></a>{@code android:anyDensity}</dt>
- <dd>Indicates whether the application includes resources to accommodate any screen
- density. Older applications (before API Level 4) are assumed unable to
- accomodate all densities and this is {@code "false"} by default. If the application has 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,
-the default value for this is {@code "true"}. Otherwise, it is {@code "false"}.
- You can explicitly supply your abilities here.
- <p>Based on the "standard" device screen density (medium dpi), the Android framework will scale
-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>
</dl></dd>
diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd
index 3df669c..480ca78 100644
--- a/docs/html/guide/topics/resources/animation-resource.jd
+++ b/docs/html/guide/topics/resources/animation-resource.jd
@@ -10,8 +10,8 @@
<li><a href="#Property">Property Animation</a></li>
<li><a href="#View">View Animation</a>
<ol>
- <li><a href="Tween">Tween animation</li>
- <li><a href="Frame">Frame animation</li>
+ <li><a href="Tween">Tween animation</a></li>
+ <li><a href="Frame">Frame animation</a></li>
</ol>
</li>
</ol>
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index 89c85e2..912b6fd 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -1418,7 +1418,7 @@
The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
-<dd>Resource pointer to a {@link android.graphics.drawable.ShapeDrawable}.</dd>
+<dd>Resource pointer to a {@link android.graphics.drawable.GradientDrawable}.</dd>
<dt>resource reference:</dt>
@@ -1458,9 +1458,7 @@
android:bottom="<em>integer</em>" />
<<a href="#size-element">size</a>
android:width="<em>integer</em>"
- android:color="<em>color</em>"
- android:dashWidth="<em>integer</em>"
- android:dashGap="<em>integer</em>" />
+ android:height="<em>integer</em>" />
<<a href="#solid-element">solid</a>
android:color="<em>color</em>" />
<<a href="#stroke-element">stroke</a>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index ea778c1..252c153 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -334,7 +334,7 @@
</td>
</tr>
<tr id="SmallestScreenWidthQualifier">
- <td>Smallest screen width</td>
+ <td>smallestWidth</td>
<td><code>sw<N>dp</code><br/><br/>
Examples:<br/>
<code>sw320dp</code><br/>
@@ -343,18 +343,23 @@
etc.
</td>
<td>
- <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>The fundamental size of a screen, as indicated by the shortest dimension of the available
+screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
+height and width (you may also think of it as the "smallest possible width" for the screen). You can
+use this qualifier to ensure that, regardless of the screen's current orientation, your
+application's has at least {@code <N>} dps of width available for it UI.</p>
+ <p>For example, if your layout requires that its smallest dimension of screen area be at
+least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
+res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
+available screen is at least 600dp, regardless of whether the 600dp side is the user-perceived
+height or width. The smallestWidth is a fixed screen size characteristic of the device; <strong>the
+device's smallestWidth does not change when the screen's orientation changes</strong>.</p>
+ <p>The smallestWidth of a device takes into account screen decorations and system UI. For
+example, if the device has some persistent UI elements on the screen that account for space along
+the axis of the smallestWidth, the system declares the smallestWidth to be smaller than the actual
+screen size, because those are screen pixels not available for your UI. Thus, the value you use
+should be the actual smallest dimension <em>required by your layout</em> (usually, this value is the
+"smallest width" that your layout supports, regardless of the screen's current orientation).</p>
<p>Some values you might use here for common screen sizes:</p>
<ul>
<li>320, for devices with screen configurations such as:
@@ -369,19 +374,22 @@
<li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
</ul>
<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>
+ the smallestWidth qualifier, the system uses the one closest to (without exceeding) the
+device's smallestWidth. </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>
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+android:requiresSmallestWidthDp}</a> attribute, which declares the minimum smallestWidth with which
+your application is compatible, and the {@link
+android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds the
+device's smallestWidth value.</p>
+ <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
</td>
</tr>
<tr id="ScreenWidthQualifier">
- <td>Screen width</td>
+ <td>Available width</td>
<td><code>w<N>dp</code><br/><br/>
Examples:<br/>
<code>w720dp</code><br/>
@@ -389,7 +397,7 @@
etc.
</td>
<td>
- <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+ <p>Specifies a minimum available 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>
@@ -403,10 +411,13 @@
<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>
+ <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
</td>
</tr>
<tr id="ScreenHeightQualifier">
- <td>Screen height</td>
+ <td>Available height</td>
<td><code>h<N>dp</code><br/><br/>
Examples:<br/>
<code>h720dp</code><br/>
@@ -414,7 +425,7 @@
etc.
</td>
<td>
- <p>Specifies a minimum screen height, in "dp" units at which the resource
+ <p>Specifies a minimum available 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>
@@ -432,6 +443,9 @@
<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>
+ <p>For more information about designing for different screens and using this
+qualifier, see the <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+Multiple Screens</a> developer guide.</p>
</td>
</tr>
<tr id="ScreenSizeQualifier">
@@ -444,30 +458,35 @@
</td>
<td>
<ul class="nolist">
- <li>{@code small}: Screens based on the space available on a
- low-density QVGA screen. Considering a portrait HVGA display, this has
- the same available width but less height—it is 3:4 vs. HVGA's
- 2:3 aspect ratio. The minimum layout size for this screen configuration
+ <li>{@code small}: Screens that are of similar size to a
+ low-density QVGA screen. The minimum layout size for a small screen
is approximately 320x426 dp units. Examples are QVGA low density and VGA high
density.</li>
- <li>{@code normal}: Screens based on the traditional
- medium-density HVGA screen. A screen is considered to be normal if it is
- at least this size (independent of density) and not larger. The minimum
- layout size for this screen configuration is approximately 320x470 dp units. Examples
+ <li>{@code normal}: Screens that are of similar size to a
+ medium-density HVGA screen. The minimum
+ layout size for a normal screen is approximately 320x470 dp units. Examples
of such screens a WQVGA low density, HVGA medium density, WVGA
high density.</li>
- <li>{@code large}: Screens based on the space available on a
- medium-density VGA screen. Such a screen has significantly more
- available space in both width and height than an HVGA display.
- The minimum layout size for this screen configuration is approximately 480x640 dp units.
+ <li>{@code large}: Screens that are of similar size to a
+ medium-density VGA screen.
+ The minimum layout size for a large screen is approximately 480x640 dp units.
Examples are VGA and WVGA medium density screens.</li>
<li>{@code xlarge}: Screens that are considerably larger than the traditional
- medium-density HVGA screen. The minimum layout size for this screen configuration
+ medium-density HVGA screen. The minimum layout size for an xlarge screen
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>
</ul>
+ <p class="note"><strong>Note:</strong> Using a size qualifier does not imply that the
+resources are <em>only</em> for screens of that size. If you do not provide alternative
+resources with qualifiers that better match the current device configuration, the system may use
+whichever resources are the <a href="#BestMatch">best match</a>.</p>
+ <p class="caution"><strong>Caution:</strong> If all your resources use a size qualifier that
+is <em>larger</em> than the current screen, the system will <strong>not</strong> use them and your
+application will crash at runtime (for example, if all layout resources are tagged with the {@code
+xlarge} qualifier, but the device is a normal-size screen).</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,
@@ -557,7 +576,8 @@
<code>mdpi</code><br/>
<code>hdpi</code><br/>
<code>xhdpi</code><br/>
- <code>nodpi</code>
+ <code>nodpi</code><br/>
+ <code>tvdpi</code>
</td>
<td>
<ul class="nolist">
@@ -569,21 +589,23 @@
Level 8</em></li>
<li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
to match the device density.</li>
+ <li>{@code tvdpi}: Screens somewhere between mdpi and hdpi; approximately 213dpi. This is
+not considered a "primary" density group. It is mostly intended for televisions and most
+apps shouldn't need it—providing mdpi and hdpi resources is sufficient for most apps and
+the system will scale them as appropriate. This qualifier was introduced with API level 13.</li>
</ul>
- <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,
- it handles screen density differently than the other qualifiers.
- In step 1 of <a href="#BestMatch">How Android finds the best
- matching directory</a> (below), screen density is always considered to
- be a match. In step 4, if the qualifier being considered is screen
- density, Android selects the best final match at that point,
- without any need to move on to step 5.
- </p>
+ <p>There is a 3:4:6:8 scaling ratio between the four primary densities (ignoring the
+tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
+ <p>If you decide that your image resources don't look good enough on a television or
+other certain devices and want to try tvdpi resources, the scaling factor is 1.33*mdpi. For
+example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.</p>
+ <p class="note"><strong>Note:</strong> Using a density qualifier does not imply that the
+resources are <em>only</em> for screens of that density. If you do not provide alternative
+resources with qualifiers that better match the current device configuration, the system may use
+whichever resources are the <a href="#BestMatch">best match</a>.</p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
-Screens</a> for more information about how to handle screen sizes and how Android might scale
-your bitmaps.</p>
+Screens</a> for more information about how to handle different screen densities and how Android
+might scale your bitmaps to fit the current density.</p>
</td>
</tr>
<tr id="TouchscreenQualifier">
@@ -993,7 +1015,10 @@
</p>
<p>By comparing the device configuration to the available alternative resources, Android selects
-drawables from {@code drawable-en-port}. It arrives at this decision using the following logic:</p>
+drawables from {@code drawable-en-port}.</p>
+
+<p>The system arrives at its decision for which resources to use with the following
+logic:</p>
<div class="figure" style="width:280px">
@@ -1069,6 +1094,14 @@
something other than English is never included in the pool of resources checked (though a
resource directory <em>without</em> the language qualifier is still included).</p>
+<p>When selecting resources based on the screen size qualifiers, the system will use resources
+designed for a screen smaller than the current screen if there are no resources that better match
+(for example, a large-size screen will use normal-size screen resources if necessary). However, if
+the only available resources are <em>larger</em> than the current screen, the system will
+<strong>not</strong> use them and your application will crash if no other resources match the device
+configuration (for example, if all layout resources are tagged with the {@code xlarge} qualifier,
+but the device is a normal-size screen).</p>
+
<p class="note"><strong>Note:</strong> The <em>precedence</em> of the qualifier (in <a
href="#table2">table 2</a>) is more important
than the number of qualifiers that exactly match the device. For example, in step 4 above, the last
diff --git a/docs/html/guide/topics/resources/string-resource.jd b/docs/html/guide/topics/resources/string-resource.jd
index 2db38f1..ecd2d48 100644
--- a/docs/html/guide/topics/resources/string-resource.jd
+++ b/docs/html/guide/topics/resources/string-resource.jd
@@ -107,7 +107,7 @@
String string = {@link android.content.Context#getString(int) getString}(R.string.hello);
</pre>
<p>You can use either {@link android.content.Context#getString(int)} or
-{@link android.content.Context#getText(int)} to retieve a string. {@link
+{@link android.content.Context#getText(int)} to retrieve a string. {@link
android.content.Context#getText(int)} will retain any rich text styling applied to the string.</p>
</dd> <!-- end example -->
@@ -233,9 +233,9 @@
<p>Note that the selection is made based on grammatical necessity. A string for <code>zero</code>
in English will be ignored even if the quantity is 0, because 0 isn't grammatically different
-from 2, or any other number except 1 ("zero books", "one book", "two books", et cetera).
+from 2, or any other number except 1 ("zero books", "one book", "two books", and so on).
Don't be misled either by the fact that, say, <code>two</code> sounds like it could only apply to
-the quantity 2: a language may require that 2, 12, 102 (et cetera) are all treated like one
+the quantity 2: a language may require that 2, 12, 102 (and so on) are all treated like one
another but differently to other quantities. Rely on your translator to know what distinctions
their language actually insists upon.
@@ -359,8 +359,15 @@
int count = getNumberOfsongsAvailable();
Resources res = {@link android.content.Context#getResources()};
String songsFound = res.{@link android.content.res.Resources#getQuantityString(int,int)
-getQuantityString}(R.plurals.numberOfSongsAvailable, count);
+getQuantityString}(R.plurals.numberOfSongsAvailable, count, count);
</pre>
+<p>When using the {@link android.content.res.Resources#getQuantityString(int,int)
+getQuantityString()} method, you need to pass the {@code count} twice if your string includes
+<a href="#FormattingAndStyling">string formatting</a> with a number. For example, for the string
+{@code %d songs found}, the first {@code count} parameter selects the appropriate plural string and
+the second {@code count} parameter is inserted into the {@code %d} placeholder. If your plural
+strings do not include string formatting, you don't need to pass the third parameter to {@link
+android.content.res.Resources#getQuantityString(int,int) getQuantityString}.</p>
</dd> <!-- end example -->
</dl>
@@ -405,7 +412,7 @@
</pre>
<p>In this example, the format string has two arguments: {@code %1$s} is a string and {@code %2$d}
-is a decimal number. You can format the string with arguements from your application like this:</p>
+is a decimal number. You can format the string with arguments from your application like this:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index b5a3f30..463ec9c 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -59,7 +59,6 @@
<li><a href="https://dl-ssl.google.com/android/adk/adk_release_0512.zip">ADK package</a></li>
</ol>
-
<h2>See also</h2>
<ol>
@@ -70,22 +69,29 @@
<h2>Where to buy</h2>
<ol>
+
+ <li><a href="http://store.arduino.cc/">
+ Arduino Store</a></li>
+
+ <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
+ DIY Drones</a></li>
+
+ <li><a href=
+ "http://www.microchip.com/android">
+ Microchip</a></li>
+
<li><a href="http://shop.moderndevice.com/products/freeduino-usb-host-board">
Modern Device</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>
+
<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>
-
- <li><a href=
- "http://www.microchip.com/android">
- Microchip</a></li>
-
- <li><a href="https://store.diydrones.com/ProductDetails.asp?ProductCode=BR-PhoneDrone">
- DIY Drones</a></li>
+ <li><a href="http://www.sparkfun.com/products/10748">
+ SparkFun</a></li>
</ol>
</div>
@@ -114,22 +120,31 @@
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>The <a href="http://store.arduino.cc/">Arduino Store</a> provides the Arduino Mega ADK
+ (in <a href="http://store.arduino.cc/eu/index.php?main_page=product_info&cPath=11_12&products_id=144">EU nations</a>
+ or <a href="http://store.arduino.cc/ww/index.php?main_page=product_info&cPath=11_12&products_id=144">non-EU nations</a>)
+ that is based on the ATmega2560 and supports the ADK firmware.</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://www.microchip.com/android">Microchip</a> provides a PIC based USB
+ microcontroller board.</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>
+
+ <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.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.sparkfun.com/products/10748">
+ SparkFun</a>'s IOIO board now has beta support for the ADK firmware.</li>
+
</ul>
<p>We expect more hardware distributers to create a variety of kits, so please stay tuned for
@@ -140,7 +155,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=ctive
+ design files and firmware code are contained in the <a href=
"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>
@@ -347,7 +362,7 @@
2.3.4 devices that support accessory mode. This library is also forward compatible with Android
3.1 or newer devices that support accessory mode. If you only care about Android 3.1 or newer
devices, all you need is API Level 12. For more information on deciding which API level to use,
- see the <a href="{@docRoot}guide/topics/USB/accessory.html#choosing">USB Accessory</a>
+ see the <a href="{@docRoot}guide/topics/usb/accessory.html#choosing">USB Accessory</a>
documentation.</li>
<li>Click <strong>File > New > Project...</strong>, then select <strong>Android >
@@ -885,4 +900,4 @@
</pre>
<p>See the <code>firmware/demokit/demokit.pde</code> file for information about how the ADK board
- reads and writes data.</p>
\ No newline at end of file
+ reads and writes data.</p>
diff --git a/docs/html/guide/topics/usb/host.jd b/docs/html/guide/topics/usb/host.jd
index 942708d..4967033 100644
--- a/docs/html/guide/topics/usb/host.jd
+++ b/docs/html/guide/topics/usb/host.jd
@@ -264,11 +264,7 @@
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
...
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
-Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
-while(deviceIterator.hasNext()){
- UsbDevice device = deviceIterator.next();
- // your code
-}
+UsbDevice device = deviceList.get("deviceName");
</pre>
<p>If desired, you can also just obtain an iterator from the hash map and process each device one
diff --git a/docs/html/images/home/market_icon.png b/docs/html/images/home/market_icon.png
new file mode 100644
index 0000000..ceb76f3
--- /dev/null
+++ b/docs/html/images/home/market_icon.png
Binary files differ
diff --git a/docs/html/images/market/version-codes.png b/docs/html/images/market/version-codes.png
new file mode 100644
index 0000000..c0c9858
--- /dev/null
+++ b/docs/html/images/market/version-codes.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index dce46f9..a8b61bf 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -11,15 +11,14 @@
</div><!-- end homeTitle -->
<div id="announcement-block">
<!-- total max width is 520px -->
- <img src="{@docRoot}assets/images/home/IO-logo-2011.png"
-alt="Android at Google IO 2011" width="200px"
-style="padding-left:22px;padding-bottom:15px;padding-top:15px;"/>
+ <img src="{@docRoot}images/home/market_icon.png"
+alt="Android Market" width="120px" style="padding:10px 53px 5px"/>
<div id="announcement" style="width:275px">
- <p>Thanks to everybody who joined us at Google I/O! If you couldn't make it or would like to
-review any of the Android sessions, they're now available on YouTube at the <a
-href="http://www.youtube.com/googledevelopers">Google Developers</a> channel, along with the keynote
-and other developer sessions. You can also find all the Google I/O Android sessions on this site, on
-the <a href="{@docRoot}videos/index.html">Videos</a> page.</p>
+ <p>We've completely redesigned Android Market for phones to make it easier to
+explore Android apps, games, and other content. Look for the new version coming to your
+Android phone!</p> <p><a
+href="http://android-developers.blogspot.com/2011/07/new-android-market-for-phones.html">Learn more
+»</a></p>
</div> <!-- end annoucement -->
</div> <!-- end annoucement-block -->
</div><!-- end topAnnouncement -->
@@ -130,14 +129,14 @@
'sdk': {
'layout':"imgLeft",
'icon':"sdk-small.png",
- 'name':"Android 3.1",
+ 'name':"Android 3.2",
'img':"honeycomb-android.png",
- 'title':"Android 3.1 now available!",
- 'desc': "<p>Android 3.1 includes new developer features such as APIs for USB "
-+ "accessories, MTP/PTP, and RTP, as well as new input events from mice, trackballs, joysticks, "
-+ "and more.</p>"
-+ "<p>For more information about all the new APIs in Android 3.1, read the "
-+ "<a href='{@docRoot}sdk/android-3.1.html'>version notes</a>.</p>"
+ 'title':"Android 3.2 is here!",
+ 'desc': "<p>Android 3.2 is a minor feature update that includes new APIs that allow you to "
++ "better target your layouts for specific screen sizes and other miscellaneous new APIs.</p>"
++ "<p>For more information about all the changes in Android 3.2, read the "
++ "<a href='{@docRoot}sdk/android-3.2.html'>version notes</a> and <a "
++ "href='{@docRoot}sdk/api_diff/13/changes.html'>diff report</a>.</p>"
/*
+ "<p>If you have an existing SDK, add Android 3.0 as an "
+ "<a href='{@docRoot}sdk/adding-components.html'>SDK "
@@ -153,10 +152,11 @@
'img':"GTV_icon_large.png",
'title':"Google TV!",
'desc': "<p>Build something big. By big, we mean <em>worthy-of-the-living-room</em> big.</p>"
- + " <p>Use <a href='http://code.google.com/tv'>Google TV</a> to bring the power of Android"
+ + " <p>Google TV brings the power of Android"
+ " and Google Chrome to television."
- + " The average American watches five hours of TV per day. Give them the web and apps"
- + " to update their status, listen to music, watch web videos, and much more...</p>"
+ + " The average American watches five hours of TV per day. Give them the apps"
+ + " to update their status, listen to music, watch web videos, and more.</p>"
+ + "<p><a href='http://code.google.com/tv'>Develop for Google TV »</a></p>"
},
diff --git a/docs/html/resources/tutorials/views/hello-gallery.jd b/docs/html/resources/tutorials/views/hello-gallery.jd
index 00757f5..5f2ed32 100644
--- a/docs/html/resources/tutorials/views/hello-gallery.jd
+++ b/docs/html/resources/tutorials/views/hello-gallery.jd
@@ -34,10 +34,10 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- Gallery g = (Gallery) findViewById(R.id.gallery);
- g.setAdapter(new ImageAdapter(this));
+ Gallery gallery = (Gallery) findViewById(R.id.gallery);
+ gallery.setAdapter(new ImageAdapter(this));
- g.setOnItemClickListener(new OnItemClickListener() {
+ gallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
Toast.makeText(HelloGallery.this, "" + position, Toast.LENGTH_SHORT).show();
}
@@ -101,10 +101,10 @@
public ImageAdapter(Context c) {
mContext = c;
- TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
- mGalleryItemBackground = a.getResourceId(
+ TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery);
+ mGalleryItemBackground = attr.getResourceId(
R.styleable.HelloGallery_android_galleryItemBackground, 0);
- a.recycle();
+ attr.recycle();
}
public int getCount() {
@@ -120,14 +120,14 @@
}
public View getView(int position, View convertView, ViewGroup parent) {
- ImageView i = new ImageView(mContext);
+ ImageView imageView = new ImageView(mContext);
- i.setImageResource(mImageIds[position]);
- i.setLayoutParams(new Gallery.LayoutParams(150, 100));
- i.setScaleType(ImageView.ScaleType.FIT_XY);
- i.setBackgroundResource(mGalleryItemBackground);
+ imageView.setImageResource(mImageIds[position]);
+ imageView.setLayoutParams(new Gallery.LayoutParams(150, 100));
+ imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+ imageView.setBackgroundResource(mGalleryItemBackground);
- return i;
+ return imageView;
}
}
</pre>
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index 6eba6f09..3f28551 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -73,51 +73,44 @@
{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
-<script type="text/javascript">
-function toggleDiv(link) {
- var toggleable = $(link).parent();
- if (toggleable.hasClass("closed")) {
- //$(".toggleme", toggleable).slideDown("fast");
- toggleable.removeClass("closed");
- toggleable.addClass("open");
- $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
- } else {
- //$(".toggleme", toggleable).slideUp("fast");
- toggleable.removeClass("open");
- toggleable.addClass("closed");
- $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
- }
- return false;
-}
-</script>
-<style>
-.toggleable {
- padding: .25em 1em 0em 1em;
- margin-bottom: 0;
-}
-.toggleme {
- padding: 1em 1em 0 2em;
- line-height:1em;
-}
-.toggleable a {
- text-decoration:none;
-}
-.toggleme a {
- text-decoration:underline;
-}
-.toggleable.closed .toggleme {
- display:none;
-}
-#jd-content .toggle-img {
- margin:0;
-}
-</style>
-<div class="toggleable opened">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
- Android 2.1, Revision 2</a> <em>(May 2010)</em></a>
- <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 2</a> <em>(May 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
<dt>Dependencies:</dt>
<dd>
@@ -136,11 +129,15 @@
</div>
</div>
-<div class="toggleable closed">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
- Android 2.1, Revision 1</a> <em>(January 2010)</em></a>
- <div class="toggleme">
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 1</a> <em>(January 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
<dt>Dependencies:</dt>
<dd>
diff --git a/docs/html/sdk/android-2.2.jd b/docs/html/sdk/android-2.2.jd
index 063a10f..c22220c 100644
--- a/docs/html/sdk/android-2.2.jd
+++ b/docs/html/sdk/android-2.2.jd
@@ -74,54 +74,46 @@
{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
-<script type="text/javascript">
-function toggleDiv(link) {
- var toggleable = $(link).parent();
- if (toggleable.hasClass("closed")) {
- //$(".toggleme", toggleable).slideDown("fast");
- toggleable.removeClass("closed");
- toggleable.addClass("open");
- $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
- } else {
- //$(".toggleme", toggleable).slideUp("fast");
- toggleable.removeClass("open");
- toggleable.addClass("closed");
- $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
- }
- return false;
-}
-</script>
-<style>
-.toggleable {
- padding: .25em 1em 0em 1em;
- margin-bottom: 0;
-}
-.toggleme {
- padding: 1em 1em 0 2em;
- line-height:1em;
-}
-.toggleable a {
- text-decoration:none;
-}
-.toggleme a {
- text-decoration:underline;
-}
-.toggleable.closed .toggleme {
- display:none;
-}
-#jd-content .toggle-img {
- margin:0;
-}
-</style>
-<div class="toggleable opened">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
- Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2010)</em></a>
- <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
<dl>
<dt>Dependencies:</dt>
<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+<dt>Dependencies:</dt>
+<dd>
<p>Requires SDK Tools r6 or higher.</p>
</dd>
@@ -138,11 +130,15 @@
</div>
</div>
-<div class="toggleable closed">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
- Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2010)</em></a>
- <div class="toggleme">
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2010)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
<dt>Dependencies:</dt>
<dd>
diff --git a/docs/html/sdk/android-2.3.3.jd b/docs/html/sdk/android-2.3.3.jd
index 10fc049..7a5b044 100644
--- a/docs/html/sdk/android-2.3.3.jd
+++ b/docs/html/sdk/android-2.3.3.jd
@@ -65,59 +65,52 @@
{@sdkPlatformVersion} platforms are installed in your SDK environment, refer to
the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
-<script type="text/javascript">
-function toggleDiv(link) {
- var toggleable = $(link).parent();
- if (toggleable.hasClass("closed")) {
- //$(".toggleme", toggleable).slideDown("fast");
- toggleable.removeClass("closed");
- toggleable.addClass("open");
- $(".toggle-img", toggleable).attr("title", "hide").attr("src", (toRoot + "assets/images/triangle-opened.png"));
- } else {
- //$(".toggleme", toggleable).slideUp("fast");
- toggleable.removeClass("open");
- toggleable.addClass("closed");
- $(".toggle-img", toggleable).attr("title", "show").attr("src", (toRoot + "assets/images/triangle-closed.png"));
- }
- return false;
-}
-</script>
-<style>
-.toggleable {
- padding: .25em 1em 0em 1em;
- margin-bottom: 0;
-}
-.toggleme {
- padding: 1em 1em 0 2em;
- line-height:1em;
-}
-.toggleable a {
- text-decoration:none;
-}
-.toggleme a {
- text-decoration:underline;
-}
-.toggleable.closed .toggleme {
- display:none;
-}
-#jd-content .toggle-img {
- margin:0;
-}
-</style>
-<div class="toggleable opened">
- <a href="#" onclick="return toggleDiv(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
- Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em></a>
- <div class="toggleme">
+<div class="toggle-content opened" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
<dt>Dependencies:</dt>
<dd>
<p>Requires SDK Tools r9 or higher.</p>
</dd>
-
</dl>
- </div>
+
+</div>
</div>
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index d73bd63..7b04446 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -62,25 +62,52 @@
refer to the "Installed Packages" listing in the Android SDK and AVD Manager.</p>
+
<div class="toggle-content opened" style="padding-left:1em;">
- <p><a href="#" onclick="return toggleContent(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt="" />
- Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
- </a></p>
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 2</a> <em>(July 2011)</em>
+</a></p>
- <div class="toggle-content-toggleme" style="padding-left:2em;">
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+
+</div>
+</div>
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 1</a> <em>(February 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
-
<dt>Dependencies:</dt>
<dd>
<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r10</a> or higher.</p>
</dd>
-
</dl>
- </div>
+</div>
</div>
diff --git a/docs/html/sdk/android-3.1.jd b/docs/html/sdk/android-3.1.jd
index 1614722..0d2d7f8 100644
--- a/docs/html/sdk/android-3.1.jd
+++ b/docs/html/sdk/android-3.1.jd
@@ -68,25 +68,79 @@
<div class="toggle-content opened" style="padding-left:1em;">
- <p><a href="#" onclick="return toggleContent(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png"
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
class="toggle-content-img" alt="" />
- Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2011)</em>
- </a></p>
+ Android {@sdkPlatformVersion}, Revision 3</a> <em>(July 2011)</em>
+</a></p>
- <div class="toggle-content-toggleme" style="padding-left:2em;">
+<div class="toggle-content-toggleme" style="padding-left:2em;">
<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r12</a> or
+higher.</p>
+</dd>
+<dt>Notes:</dt>
+<dd>
+<p>Improvements to the platform's rendering library to support the visual layout editor in the ADT
+Eclipse plugin. This revision allows for more drawing features in ADT and fixes several
+bugs in the previous rendering library. It also unlocks several editor features that were added in
+ADT 12.</p>
+</dd>
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 2</a> <em>(May 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
<dt>Dependencies:</dt>
<dd>
<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r11</a> or
higher.</p>
</dd>
-
+<dt>Notes:</dt>
+<dd>
+<p>Fixes an issue with the visual layout editor rendering library that prevented Android 3.1 from
+running in ADT.</p>
+</dd>
</dl>
- </div>
+</div>
+</div>
+
+
+<div class="toggle-content closed" style="padding-left:1em;">
+
+<p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
+class="toggle-content-img" alt="" />
+ Android {@sdkPlatformVersion}, Revision 1</a> <em>(May 2011)</em>
+</a></p>
+
+<div class="toggle-content-toggleme" style="padding-left:2em;">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>Requires <a href="{@docRoot}sdk/tools-notes.html">SDK Tools r11</a> or
+higher.</p>
+</dd>
+</dl>
+
+</div>
</div>
diff --git a/docs/html/sdk/compatibility-library.jd b/docs/html/sdk/compatibility-library.jd
index d4669e5..c8cd5b2 100644
--- a/docs/html/sdk/compatibility-library.jd
+++ b/docs/html/sdk/compatibility-library.jd
@@ -1,4 +1,4 @@
-page.title=Compatibility Library
+page.title=Compatibility Package
@jd:body
@@ -8,9 +8,10 @@
<h2>In this document</h2>
<ol>
<li><a href="#Notes">Revisions</a></li>
- <li><a href="#Installing">Installing the Compatibility Library</a></li>
- <li><a href="#SettingUp">Setting Up a Project to Use the Library</a></li>
- <li><a href="#Using">Using Some of the Library APIs</a></li>
+ <li><a href="#Downloading">Downloading the Compatibility Package</a></li>
+ <li><a href="#SettingUp">Setting Up a Project to Use a Library</a></li>
+ <li><a href="#Using">Using the v4 Library APIs</a></li>
+ <li><a href="#Docs">Reference Docs</a></li>
<li><a href="#Samples">Samples</a></li>
</ol>
@@ -26,42 +27,92 @@
<p><em>Minimum API level supported:</em> <b>4</b></p>
-<p>The Compatibility Library is a static library you can add to your Android application in order to
-use APIs not available in older versions of the Android platform. The primary goal of the library is
-to provide APIs introduced in Andriod 3.0 for older versions of Android so that all applications can
-use them.</p>
+<p>The Compatibility Package includes static "support libraries" that you can add to your Android
+application in order to use APIs that are either not available for older platform versions or that
+offer "utility" APIs that aren't a part of the framework APIs. The goal is to simplify your
+development by offering more APIs that you can bundle with your application so you can
+worry less about platform versions.</p>
-<p>If you're not able to use APIs introduced in Android 3.0 directly, because you want to remain
-backward-compatible, the Compatibility Library provides your application access to self-contained
-versions of some of the latest APIs that you can use with older versions of Android. Most
-importantly, the library provides implementations of the {@link android.app.Fragment} and {@link
-android.content.Loader} APIs, so you can use them in a way that's compatible with devices running
-Android 1.6 (API level 4) and higher. Thus, you can more easily create a single APK that supports a
-majority of devices and provide larger devices (such as tablets) a fully optimized experience by
-using <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> in your activity
-design.</p>
+<p class="note"><strong>Note:</strong> The Compatibility Package includes more than one support
+library. Each one has a different <em>minimum API level</em>. For example, one library requires API
+level 4 or higher, while another requires API level 13 or higher. The minimum version is indicated
+by the directory name, such as {@code v4/} and {@code v13/}.</p>
<h2 id="Notes">Revisions</h2>
<p>The sections below provide notes about successive releases of
-the Compatibility Library, as denoted by revision number.</p>
+the Compatibility Package, as denoted by revision number.</p>
<div class="toggle-content open">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" />
- Compatibility Library, revision 2 (May 2011)
+ Compatibility Package, revision 3 (July 2011)
</a></p>
<div class="toggle-content-toggleme" style="padding-left:2em">
<dl>
- <dt>Changes:</dt>
+ <dt>Changes for v4 support library:</dt>
+ <dd>
+ <ul>
+ <li>Adds support for {@link android.app.Fragment.SavedState}</li>
+ <li>Adds {@code MotionEventCompat} to support newer {@link
+android.view.MotionEvent} APIs</li>
+ <li>Adds {@code VelocityTrackerCompat} to support a newer {@link
+android.view.VelocityTracker} APIs</li>
+ <li>Adds {@code ViewConfigurationCompat} to support a newer {@link
+android.view.ViewConfiguration} APIs</li>
+ <li>All new APIs (available only in the support library) that allow you to create UIs
+with horizontal paging, allowing users to swipe left and right between content views. Classes to
+support this include:
+ <ul>
+ <li>{@code ViewPager}: A {@link android.view.ViewGroup} that manages the
+layout for the child views, which the user can swipe between.</li>
+ <li>{@code PagerAdapter}: An adapter that populates the {@code ViewPager} with the
+views that represent each page.</li>
+ <li>{@code FragmentPagerAdapter}: An extension of {@code PagerAdapter} for flipping
+between fragments.</li>
+ <li>{@code FragmentStatePagerAdapter}: An extension of {@code PagerAdapter} for
+flipping between fragments that uses the library's support for {@link
+android.app.Fragment.SavedState}.</li>
+ </ul>
+ </li>
+ </ul>
+ </dd>
+ <dt>New v13 support library:</dt>
+ <dd>
+ <ul>
+ <li>Includes the {@code FragmentPagerAdapter} and {@code FragmentStatePagerAdapter}
+to support the horizontal paging.
+ <p>These are exactly the same as the APIs added to the v4 support library, but rely on
+other platform components in Android 3.2. Use this library instead of v4 if you're developing for
+Android 3.2 and higher (all other APIs in the v4 library are already available with API level
+13).</p>
+ </li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+
+</div>
+
+
+<div class="toggle-content closed">
+
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" />
+ Compatibility Package, revision 2 (May 2011)
+ </a></p>
+
+ <div class="toggle-content-toggleme" style="padding-left:2em">
+ <dl>
+ <dt>Changes for v4 library:</dt>
<dd>
<ul>
- <li>Support for fragment animations.</li>
- <li>Fix {@code Fragment.onActivityResult()} bug.</li>
+ <li>Support for fragment animations</li>
+ <li>Fix {@code Fragment.onActivityResult()} bug</li>
</ul>
</dd>
</dl>
@@ -74,21 +125,21 @@
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" />
- Compatibility Library, revision 1 (March 2011)
+ Compatibility Package, revision 1 (March 2011)
</a></p>
<div class="toggle-content-toggleme" style="padding-left:2em">
- <p>Initial release of the library.</p>
+ <p>Initial release with the v4 library.</p>
</div>
</div>
-<h2 id="Installing">Installing the Compatibility Library</h2>
+<h2 id="Downloading">Downloading the Compatibility Package</h2>
-<p>The Compatibility Library is provided as a downloadable package from the Android SDK and AVD
-Manager. To install the library:</p>
+<p>The Compatibility Package is provided as a downloadable package from the Android SDK and AVD
+Manager. To install:</p>
<ol>
<li>Launch the SDK and AVD Manager.
@@ -101,43 +152,53 @@
<li>Proceed to install the package.</li>
</ol>
-<p>When done, all files (including source code, samples, and the {@code .jar} file) are saved
-into the <code><sdk>/extras/android/compatibility/</code> directory. The next directory
-name is {@code v4}, which indicates the lowest compatible version for the library within. That
-is, the code in {@code v4/} supports API level 4 and above. (There may be future libraries that
-have a different minimum version, so they will be saved alongside this one.)</p>
+<p>When done, all files (including source code, samples, and the {@code .jar} files) are saved
+into the <code><sdk>/extras/android/compatibility/</code> directory. This directory contains
+each of the different support libraries, such as the library for API level 4 and up and the library
+for API level 13 and up, each named with the respective version (such as {@code v4/}).</p>
-<h2 id="SettingUp">Setting Up a Project to Use the Library</h2>
+<h2 id="SettingUp">Setting Up a Project to Use a Library</h2>
-<p>To add the Compatibility Library to your Android project:</p>
+<p>To add one of the libraries to your Android project:</p>
<ol>
<li>In your Android project, create a directory named {@code libs} at the root of your
project (next to {@code src/}, {@code res/}, etc.)</li>
- <li>Navigate to {@code <sdk>/extras/android/compatibility/v4/}.</li>
- <li>Copy the {@code android-support-v4.jar} file into your project {@code libs/} directory.</li>
- <li>Add the JAR to your project build path. In Eclipse, right-click the JAR file in the
-Package Explorer, select <strong>Build Path</strong> > <strong>Add to Build Path</strong>.
-You should then see the JAR file appear in a new directory called Referenced Libraries.</li>
+ <li>Locate the JAR file for the library you want to use and copy it into the {@code
+libs/} directory.
+ <p>For example, the library that supports API level 4 and up is located at {@code
+<sdk>/extras/android/compatibility/v4/android-support-v4.jar}.</p>
+ </li>
+ <li>Add the JAR to your project build path.
+ <p>In Eclipse, right-click the JAR file in the Package Explorer, select <strong>Build
+Path</strong> > <strong>Add to Build Path</strong>. You should then see the JAR file appear in a
+new directory called Referenced Libraries.</p>
+ </li>
</ol>
-<p>Your application is now ready to use fragments, loaders and other APIs from the library. All the
-provided APIs are in the {@code android.support.v4} package.</p>
+<p>Your application is now ready to use the library APIs. All the
+provided APIs are available in the {@code android.support} package (for
+example, {@code android.support.v4}).</p>
+
+<p class="note"><strong>Tip:</strong> To see the library APIs in action, take a look at the sample
+apps in {@code extras/android/compatibility/<version>/samples/}.</p>
<p class="warning"><strong>Warning:</strong> Be certain that you not confuse the standard
-{@code android} packages with those in {@code android.support.v4}. Some code completion tools might
+{@code android} packages with those in {@code android.support} library. Some code completion tools
+might
get this wrong, especially if you're building against recent versions of the platform. To be safe,
keep your build target set to the same version as you have defined for your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
-and double check the import statements for classes that are duplicated in the Compatibility
-Library, such as {@code SimpleCursorAdapter}.</p>
+and double check the import statements for classes that also exist in the support library, such as
+{@code SimpleCursorAdapter}.</p>
-<h2 id="Using">Using Some of the Library APIs</h2>
+<h2 id="Using">Using the v4 Library APIs</h2>
-<p>The Compatibility Library provides access to several classes introduced with Android 3.0, plus
-some updated version of existing classes. Some of the most useful and notable classes in the
-library are:</p>
+<p>The support library for v4 provides access to several classes introduced with Android 3.0 and
+beyond, plus some updated version of existing classes, and even some APIs that currently don't
+exist in the Android platform. Some of the most useful and notable classes that have
+counterparts in the v4 support library are:</p>
<ul>
<li>{@link android.app.Fragment}</li>
@@ -152,8 +213,8 @@
</ul>
<p>For each of the classes above (and others not listed), the APIs work almost exactly the same
-as the counterparts in the latest version of the Android platform. Thus, you can usually refer to
-the latest reference documentation for information about the supported APIs. There are some
+as the counterparts in the latest Android platform. Thus, you can usually refer to
+the online documentation for information about the supported APIs. There are some
differences, however. Most notably:</p>
<ul>
@@ -181,18 +242,6 @@
</li>
</ul>
-<p>The Compatibility Library currently does not provide reference documentation for the included
-APIs. To generate your own set, using the {@code javadoc} tool, perform the
-following from a command line:</p>
-
-<pre class="no-pretty-print">
-cd <sdk>/extras/android/compatibility/v4/
-mkdir docs
-javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs
-</pre>
-<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p>
-
-
<div class="note"><p><strong>Tip:</strong> To enable the Holographic theme on devices
running Android 3.0 or higher, declare in your manifest file that your application targets
API level 11. For example:</p>
@@ -208,16 +257,30 @@
Apps for Android 3.0</a>.</p>
+<h2 id="Docs">Reference Docs</h2>
+
+<p>The libraries currently do not provide reference documentation for the included APIs. To generate
+your own set using the {@code javadoc} tool, perform the following from a command (as appropriate
+for the library version you're using). In this example, documentation is generated for the v4
+library:</p>
+
+<pre class="no-pretty-print">
+cd <sdk>/extras/android/compatibility/v4/
+mkdir docs
+javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs
+</pre>
+<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p>
+
+
<h2 id="Samples">Samples</h2>
-<p>If you want to see some sample code that uses the Compatibility Library, take a look at the
-<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/support/index.html">API
-Demos</a> sample code that's included with the Samples package you can download from the AVD and SDK
-Manager.</p>
+<p>If you want to see some code that uses the support libraries, samples are included with the
+Compatibility Package, inside each support library directory. For example, at {@code
+extras/android/compatibility/v4/samples/}.</p>
<p>Additionally, the <a href="http://code.google.com/p/iosched/">Google I/O App</a> is a complete
-application that uses the library to provide a single APK for both handsets and tablets and also
-demonstrates some of Android's best practices in Android UI design.</p>
+application that uses the v4 support library to provide a single APK for both handsets and tablets
+and also demonstrates some of Android's best practices in Android UI design.</p>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 829ed52..1b1fc8d 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -145,8 +145,8 @@
<li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r12</a> <span
class="new">new!</span></li>
<li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
- <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library,
-r2</a></li>
+ <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Package,
+r3</a> <span class="new">new!</span></li>
</ul>
</li>
<li>
@@ -183,8 +183,8 @@
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6 <span
- class="new">new!</span></a>
+ <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r6</a>
+ <span class="new">new!</span>
</li>
<li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
</ul>
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 2d8e877..986f32c 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -110,11 +110,11 @@
handle->extendedData.clear();
}
-int BpDrmManagerService::addUniqueId(int uniqueId) {
+int BpDrmManagerService::addUniqueId(bool isNative) {
LOGV("add uniqueid");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
- data.writeInt32(uniqueId);
+ data.writeInt32(isNative);
remote()->transact(ADD_UNIQUEID, data, &reply);
return reply.readInt32();
}
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1809619..3e4fe8c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -49,32 +49,42 @@
}
-int DrmManager::addUniqueId(int uniqueId) {
+int DrmManager::addUniqueId(bool isNative) {
Mutex::Autolock _l(mLock);
- if (0 == uniqueId) {
- int temp = 0;
- bool foundUniqueId = false;
- srand(time(NULL));
- while (!foundUniqueId) {
- const int size = mUniqueIdVector.size();
- temp = rand() % 100;
+ int temp = 0;
+ bool foundUniqueId = false;
+ const int size = mUniqueIdVector.size();
+ const int uniqueIdRange = 0xfff;
+ int maxLoopTimes = (uniqueIdRange - 1) / 2;
+ srand(time(NULL));
- int index = 0;
- for (; index < size; ++index) {
- if (mUniqueIdVector.itemAt(index) == temp) {
- foundUniqueId = false;
- break;
- }
- }
- if (index == size) {
- foundUniqueId = true;
+ while (!foundUniqueId) {
+ temp = rand() & uniqueIdRange;
+
+ if (isNative) {
+ // set a flag to differentiate DrmManagerClient
+ // created from native side and java side
+ temp |= 0x1000;
+ }
+
+ int index = 0;
+ for (; index < size; ++index) {
+ if (mUniqueIdVector.itemAt(index) == temp) {
+ foundUniqueId = false;
+ break;
}
}
- uniqueId = temp;
+ if (index == size) {
+ foundUniqueId = true;
+ }
+
+ maxLoopTimes --;
+ LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session");
}
- mUniqueIdVector.push(uniqueId);
- return uniqueId;
+
+ mUniqueIdVector.push(temp);
+ return temp;
}
void DrmManager::removeUniqueId(int uniqueId) {
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 583669e..7ebcac3 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -78,8 +78,8 @@
delete mDrmManager; mDrmManager = NULL;
}
-int DrmManagerService::addUniqueId(int uniqueId) {
- return mDrmManager->addUniqueId(uniqueId);
+int DrmManagerService::addUniqueId(bool isNative) {
+ return mDrmManager->addUniqueId(isNative);
}
void DrmManagerService::removeUniqueId(int uniqueId) {
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index f3a0343..9a7194c 100755
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -248,9 +248,7 @@
mEventHandler = new EventHandler(eventThread.getLooper());
// save the unique id
- mUniqueId = hashCode();
-
- _initialize(mUniqueId, new WeakReference<DrmManagerClient>(this));
+ mUniqueId = _initialize(new WeakReference<DrmManagerClient>(this));
}
protected void finalize() {
@@ -794,7 +792,7 @@
}
// private native interfaces
- private native void _initialize(int uniqueId, Object weak_this);
+ private native int _initialize(Object weak_this);
private native void _finalize(int uniqueId);
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index e131839..80a8447 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -224,11 +224,12 @@
return sp<DrmManagerClientImpl>(client);
}
-static void android_drm_DrmManagerClient_initialize(
- JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
+static jint android_drm_DrmManagerClient_initialize(
+ JNIEnv* env, jobject thiz, jobject weak_thiz) {
LOGV("initialize - Enter");
- sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId);
+ int uniqueId = 0;
+ sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId, false);
drmManager->addClient(uniqueId);
// Set the listener to DrmManager
@@ -237,6 +238,8 @@
setDrmManagerClientImpl(env, thiz, drmManager);
LOGV("initialize - Exit");
+
+ return uniqueId;
}
static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) {
@@ -711,7 +714,7 @@
static JNINativeMethod nativeMethods[] = {
- {"_initialize", "(ILjava/lang/Object;)V",
+ {"_initialize", "(Ljava/lang/Object;)I",
(void*)android_drm_DrmManagerClient_initialize},
{"_finalize", "(I)V",
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index b50199f..c9c0d57 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -24,7 +24,7 @@
DrmManagerClient::DrmManagerClient():
mUniqueId(0), mDrmManagerClientImpl(NULL) {
- mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+ mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true);
mDrmManagerClientImpl->addClient(mUniqueId);
}
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a36bd4a..67f58ca 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -33,13 +33,10 @@
sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier;
const String8 DrmManagerClientImpl::EMPTY_STRING("");
-DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
- if (0 == *pUniqueId) {
- int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId);
- *pUniqueId = uniqueId;
- } else {
- getDrmManagerService()->addUniqueId(*pUniqueId);
- }
+DrmManagerClientImpl* DrmManagerClientImpl::create(
+ int* pUniqueId, bool isNative) {
+ *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+
return new DrmManagerClientImpl();
}
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index af2c2a8..ac2b946 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -53,7 +53,7 @@
virtual ~DrmManager();
public:
- int addUniqueId(int uniqueId);
+ int addUniqueId(bool isNative);
void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 564896b..e3338d9 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -38,7 +38,7 @@
DrmManagerClientImpl() { }
public:
- static DrmManagerClientImpl* create(int* pUniqueId);
+ static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
static void remove(int uniqueId);
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index 227496a..9cb5804 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -46,7 +46,7 @@
virtual ~DrmManagerService();
public:
- int addUniqueId(int uniqueId);
+ int addUniqueId(bool isNative);
void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 7727e55..b9618bb 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -81,7 +81,7 @@
DECLARE_META_INTERFACE(DrmManagerService);
public:
- virtual int addUniqueId(int uniqueId) = 0;
+ virtual int addUniqueId(bool isNative) = 0;
virtual void removeUniqueId(int uniqueId) = 0;
@@ -167,7 +167,7 @@
BpDrmManagerService(const sp<IBinder>& impl)
: BpInterface<IDrmManagerService>(impl) {}
- virtual int addUniqueId(int uniqueId);
+ virtual int addUniqueId(bool isNative);
virtual void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index b61e3d3..4a5afcf 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -143,7 +143,13 @@
* Register a callback to be invoked when the caller required to
* receive necessary information
*
- * @param[in] uniqueId Unique identifier for a session
+ * @param[in] uniqueId Unique identifier for a session. uniqueId is a random
+ * number generated in the DRM service. If the DrmManagerClient
+ * is created in native code, uniqueId will be a number ranged
+ * from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId
+ * will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in
+ * uniqueId could be used in DRM plugins to differentiate native
+ * OnInfoListener and Java OnInfoListener.
* @param[in] infoListener Listener
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 2220f96..7efdc6c 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -33,7 +33,7 @@
* <p>
* The simplest way to create a frame-by-frame animation is to define the animation in an XML
* file, placed in the res/drawable/ folder, and set it as the background to a View object. Then, call
- * {@link #run()} to start the animation.
+ * {@link #start()} to run the animation.
* <p>
* An AnimationDrawable defined in XML consists of a single <code><animation-list></code> element,
* and a series of nested <code><item></code> tags. Each item defines a frame of the animation.
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 63e7dd1..2e55c48 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -97,6 +97,13 @@
}
}
+ /**
+ * @return name of the renderscript object
+ */
+ public String getName() {
+ return mName;
+ }
+
protected void finalize() throws Throwable {
if (!mDestroyed) {
if(mID != 0 && mRS.isAlive()) {
diff --git a/graphics/java/android/renderscript/RSTextureView.java b/graphics/java/android/renderscript/RSTextureView.java
index 6046ee1..b8dd577 100644
--- a/graphics/java/android/renderscript/RSTextureView.java
+++ b/graphics/java/android/renderscript/RSTextureView.java
@@ -29,9 +29,9 @@
import android.view.TextureView;
/**
- * The Surface View for a graphics renderscript (RenderScriptGL) to draw on.
+ * The Texture View for a graphics renderscript (RenderScriptGL)
+ * to draw on.
*
- * @hide
*/
public class RSTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private RenderScriptGL mRS;
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 8b14f99..935b75a 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -200,8 +200,6 @@
/**
* Bind an os surface
*
- * @hide
- *
* @param w
* @param h
* @param sur
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 11aa134..d00c428 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -44,7 +44,6 @@
}
/**
- * @hide
* Only intended for use by generated reflected code.
*
* @param slot
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 83d4f6d..d2f398a 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -455,6 +455,16 @@
// Example: "176x144,1280x720". Read only.
static const char KEY_SUPPORTED_VIDEO_SIZES[];
+ // The maximum number of detected faces supported by hardware face
+ // detection. If the value is 0, hardware face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_HW[];
+
+ // The maximum number of detected faces supported by software face
+ // detection. If the value is 0, software face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_SW[];
+
// Preferred preview frame size in pixels for video recording.
// The width and height must be one of the supported sizes retrieved
// via KEY_SUPPORTED_PREVIEW_SIZES. This key can be used only when
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 134c208..2a8e725 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -211,7 +211,6 @@
// all slots.
void freeAllBuffers();
static bool isExternalFormat(uint32_t format);
- static GLenum getTextureTarget(uint32_t format);
private:
@@ -348,10 +347,6 @@
// reset mCurrentTexture to INVALID_BUFFER_SLOT.
int mCurrentTexture;
- // mCurrentTextureTarget is the GLES texture target to be used with the
- // current texture.
- GLenum mCurrentTextureTarget;
-
// mCurrentTextureBuf is the graphic buffer of the current texture. It's
// possible that this buffer is not associated with any buffer slot, so we
// must track it separately in order to support the getCurrentBuffer method.
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 56f029f..57f9e15 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -135,24 +135,12 @@
// a timestamp is auto-generated when queueBuffer is called.
int64_t mTimestamp;
- // mQueryWidth is the width returned by query(). It is set to width
- // of the last dequeued buffer or to mReqWidth if no buffer was dequeued.
- uint32_t mQueryWidth;
-
- // mQueryHeight is the height returned by query(). It is set to height
- // of the last dequeued buffer or to mReqHeight if no buffer was dequeued.
- uint32_t mQueryHeight;
-
- // mQueryFormat is the format returned by query(). It is set to the last
- // dequeued format or to mReqFormat if no buffer was dequeued.
- uint32_t mQueryFormat;
-
// mDefaultWidth is default width of the window, regardless of the
- // set_dimension call
+ // native_window_set_buffers_dimensions call
uint32_t mDefaultWidth;
// mDefaultHeight is default width of the window, regardless of the
- // set_dimension call
+ // native_window_set_buffers_dimensions call
uint32_t mDefaultHeight;
// mTransformHint is the transform probably applied to buffers of this
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 496b23e..1417416 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
#include <media/IEffect.h>
#include <media/IEffectClient.h>
#include <hardware/audio_effect.h>
@@ -111,6 +112,36 @@
/*
+ * Returns a list of descriptors corresponding to the pre processings enabled by default
+ * on an AudioRecord with the supplied audio session ID.
+ *
+ * Parameters:
+ * audioSession: audio session ID.
+ * descriptors: address where the effect descriptors should be returned.
+ * count: as input, the maximum number of descriptor than should be returned
+ * as output, the number of descriptor returned if status is NO_ERROR or the actual
+ * number of enabled pre processings if status is NO_MEMORY
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * NO_MEMORY the number of descriptor to return is more than the maximum number
+ * indicated by count.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid audio session or descriptor pointers
+ *
+ * Returned value
+ * *descriptor updated with descriptors of pre processings enabled by default
+ * *count number of descriptors returned if returned status is N_ERROR.
+ * total number of pre processing enabled by default if returned status is
+ * NO_MEMORY. This happens if the count passed as input is less than the number
+ * of descriptors to return
+ */
+ static status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
+
+ /*
* Events used by callback function (effect_callback_t).
*/
enum event_type {
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 86b9f85..ed265e1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -85,6 +85,9 @@
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count) = 0;
};
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 007aea6..ec84e25 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -43,7 +43,6 @@
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;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 1136f6c..1a67671 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -130,13 +130,22 @@
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
};
-enum media_set_parameter_keys {
- KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
- KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,
+// Keep KEY_PARAMETER_* in sync with MediaPlayer.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get. But as of now, all parameters are either set only or get only.
+enum media_parameter_keys {
+ KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000, // set only
+ KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001, // set only
// Streaming/buffering parameters
- KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only
+
+ // Return a Parcel containing a single int, which is the channel count of the
+ // audio track, or zero for error (e.g. no audio track) or unknown.
+ KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200, // get only
+
};
+
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
class MediaPlayerListener: virtual public RefBase
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 72d3736..30db642 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -215,7 +215,6 @@
status_t setAudioEncoder(int ae);
status_t setOutputFile(const char* path);
status_t setOutputFile(int fd, int64_t offset, int64_t length);
- status_t setOutputFileAuxiliary(int fd);
status_t setVideoSize(int width, int height);
status_t setVideoFrameRate(int frames_per_second);
status_t setParameters(const String8& params);
@@ -249,7 +248,6 @@
bool mIsAudioEncoderSet;
bool mIsVideoEncoderSet;
bool mIsOutputFileSet;
- bool mIsAuxiliaryOutputFileSet;
Mutex mLock;
Mutex mNotifyLock;
};
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index f07ebba..0e264c7 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -53,27 +53,10 @@
void startQuickReadReturns();
private:
- // If true, will use still camera takePicture() for time lapse frames
- // If false, will use the videocamera frames instead.
- bool mUseStillCameraForTimeLapse;
-
- // Size of picture taken from still camera. This may be larger than the size
- // of the video, as still camera may not support the exact video resolution
- // demanded. See setPictureSizeToClosestSupported().
- int32_t mPictureWidth;
- int32_t mPictureHeight;
-
// size of the encoded video.
int32_t mVideoWidth;
int32_t mVideoHeight;
- // True if we need to crop the still camera image to get the video frame.
- bool mNeedCropping;
-
- // Start location of the cropping rectangle.
- int32_t mCropRectStartX;
- int32_t mCropRectStartY;
-
// Time between capture of two frames during time lapse recording
// Negative value indicates that timelapse is disabled.
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -84,9 +67,6 @@
// Real timestamp of the last encoded time lapse frame
int64_t mLastTimeLapseFrameRealTimestampUs;
- // Thread id of thread which takes still picture and sleeps in a loop.
- pthread_t mThreadTimeLapse;
-
// Variable set in dataCallbackTimestamp() to help skipCurrentFrame()
// to know if current frame needs to be skipped.
bool mSkipCurrentFrame;
@@ -111,9 +91,6 @@
// Lock for accessing quick stop variables.
Mutex mQuickStopLock;
- // Condition variable to wake up still picture thread.
- Condition mTakePictureCondition;
-
// mQuickStop is set to true if we use quick read() returns, otherwise it is set
// to false. Once in this mode read() return a copy of the last read frame
// with the same time stamp. See startQuickReadReturns().
@@ -148,32 +125,13 @@
// Wrapper over CameraSource::read() to implement quick stop.
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
- // For still camera case starts a thread which calls camera's takePicture()
- // in a loop. For video camera case, just starts the camera's video recording.
- virtual void startCameraRecording();
-
- // For still camera case joins the thread created in startCameraRecording().
// For video camera case, just stops the camera's video recording.
virtual void stopCameraRecording();
- // For still camera case don't need to do anything as memory is locally
- // allocated with refcounting.
- // For video camera case just tell the camera to release the frame.
- virtual void releaseRecordingFrame(const sp<IMemory>& frame);
-
// mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
// frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
virtual bool skipCurrentFrame(int64_t timestampUs);
- // Handles the callback to handle raw frame data from the still camera.
- // Creates a copy of the frame data as the camera can reuse the frame memory
- // once this callback returns. The function also sets a new timstamp corresponding
- // to one frame time ahead of the last encoded frame's time stamp. It then
- // calls dataCallbackTimestamp() of the base class with the copied data and the
- // modified timestamp, which will think that it recieved the frame from a video
- // camera and proceed as usual.
- virtual void dataCallback(int32_t msgType, const sp<IMemory> &data);
-
// In the video camera case calls skipFrameAndModifyTimeStamp() to modify
// timestamp and set mSkipCurrentFrame.
// Then it calls the base CameraSource::dataCallbackTimestamp()
@@ -189,24 +147,6 @@
// Otherwise returns false.
bool trySettingVideoSize(int32_t width, int32_t height);
- // The still camera may not support the demanded video width and height.
- // We look for the supported picture sizes from the still camera and
- // choose the smallest one with either dimensions higher than the corresponding
- // video dimensions. The still picture will be cropped to get the video frame.
- // The function returns true if the camera supports picture sizes greater than
- // or equal to the passed in width and height, and false otherwise.
- bool setPictureSizeToClosestSupported(int32_t width, int32_t height);
-
- // Computes the offset of the rectangle from where to start cropping the
- // still image into the video frame. We choose the center of the image to be
- // cropped. The offset is stored in (mCropRectStartX, mCropRectStartY).
- bool computeCropRectangleOffset();
-
- // Crops the source data into a smaller image starting at
- // (mCropRectStartX, mCropRectStartY) and of the size of the video frame.
- // The data is returned into a newly allocated IMemory.
- sp<IMemory> cropYUVImage(const sp<IMemory> &source_data);
-
// When video camera is used for time lapse capture, returns true
// until enough time has passed for the next time lapse frame. When
// the frame needs to be encoded, it returns false and also modifies
@@ -217,22 +157,6 @@
// Wrapper to enter threadTimeLapseEntry()
static void *ThreadTimeLapseWrapper(void *me);
- // Runs a loop which sleeps until a still picture is required
- // and then calls mCamera->takePicture() to take the still picture.
- // Used only in the case mUseStillCameraForTimeLapse = true.
- void threadTimeLapseEntry();
-
- // Wrapper to enter threadStartPreview()
- static void *ThreadStartPreviewWrapper(void *me);
-
- // Starts the camera's preview.
- void threadStartPreview();
-
- // Starts thread ThreadStartPreviewWrapper() for restarting preview.
- // Needs to be done in a thread so that dataCallback() which calls this function
- // can return, and the camera can know that takePicture() is done.
- void restartPreview();
-
// Creates a copy of source_data into a new memory of final type MemoryBase.
sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 52a3257..4eaf8ac 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -69,6 +69,16 @@
* kMetadataBufferTypeGrallocSource is used to indicate that
* the payload of the metadata buffers can be interpreted as
* a buffer_handle_t.
+ * So in this case,the metadata that the encoder receives
+ * will have a byte stream that consists of two parts:
+ * 1. First, there is an integer indicating that it is a GRAlloc
+ * source (kMetadataBufferTypeGrallocSource)
+ * 2. This is followed by the buffer_handle_t that is a handle to the
+ * GRalloc buffer. The encoder needs to interpret this GRalloc handle
+ * and encode the frames.
+ * --------------------------------------------------------------
+ * | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+ * --------------------------------------------------------------
*/
kMetadataBufferTypeGrallocSource = 1,
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 56bd9c3..fab258c 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -63,6 +63,10 @@
MediaBuffer **buffer, const ReadOptions *options = NULL);
virtual sp<MetaData> getFormat();
+ // Pass the metadata over to the buffer, call when you have the lock
+ void passMetadataBufferLocked(MediaBuffer **buffer);
+ bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
// Get / Set the frame rate used for encoding. Default fps = 30
status_t setFrameRate(int32_t fps) ;
int32_t getFrameRate( ) const;
@@ -152,7 +156,7 @@
status_t setBufferCountServer(int bufferCount);
// getTimestamp retrieves the timestamp associated with the image
- // set by the most recent call to updateFrameInfoLocked().
+ // set by the most recent call to read()
//
// The timestamp is in nanoseconds, and is monotonically increasing. Its
// other semantics (zero point, etc) are source-dependent and should be
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
new file mode 100644
index 0000000..1723f04
--- /dev/null
+++ b/include/powermanager/IPowerManager.h
@@ -0,0 +1,41 @@
+/*
+ * 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_IPOWERMANAGER_H
+#define ANDROID_IPOWERMANAGER_H
+
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// must be kept in sync with interface defined in IPowerManager.aidl
+class IPowerManager : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(PowerManager);
+
+ virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag) = 0;
+ virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IPOWERMANAGER_H
diff --git a/include/powermanager/PowerManager.h b/include/powermanager/PowerManager.h
new file mode 100644
index 0000000..4590174
--- /dev/null
+++ b/include/powermanager/PowerManager.h
@@ -0,0 +1,29 @@
+/*
+ * 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_POWERMANAGER_H
+#define ANDROID_POWERMANAGER_H
+
+namespace android {
+
+// must be kept in sync with definitions in PowerManager.java
+enum {
+ POWERMANAGER_PARTIAL_WAKE_LOCK = 1, // equals PowerManager.PARTIAL_WAKE_LOCK constant
+};
+
+}; // namespace android
+
+#endif // ANDROID_POWERMANAGER_H
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 9c352ad..0460bbd 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -122,7 +122,10 @@
uint32_t reserved[2];
};
+ explicit Surface(const sp<ISurfaceTexture>& st);
+
static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
+
static sp<Surface> readFromParcel(const Parcel& data);
static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid();
@@ -147,14 +150,14 @@
Surface& operator = (Surface& rhs);
Surface(const Surface& rhs);
- Surface(const sp<SurfaceControl>& control);
+ explicit Surface(const sp<SurfaceControl>& control);
Surface(const Parcel& data, const sp<IBinder>& ref);
~Surface();
/*
* private stuff...
*/
- void init();
+ void init(const sp<ISurfaceTexture>& surfaceTexture);
static void cleanCachedSurfacesLocked();
diff --git a/include/utils/ZipFileRO.h b/include/utils/ZipFileRO.h
index 3a99979..547e36a 100644
--- a/include/utils/ZipFileRO.h
+++ b/include/utils/ZipFileRO.h
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <time.h>
namespace android {
@@ -174,6 +175,20 @@
size_t uncompLen, size_t compLen);
/*
+ * Utility function to convert ZIP's time format to a timespec struct.
+ */
+ static inline void zipTimeToTimespec(long when, struct tm* timespec) {
+ const long date = when >> 16;
+ timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980
+ timespec->tm_mon = (date >> 5) & 0x0F;
+ timespec->tm_mday = date & 0x1F;
+
+ timespec->tm_hour = (when >> 11) & 0x1F;
+ timespec->tm_min = (when >> 5) & 0x3F;
+ timespec->tm_sec = (when & 0x1F) << 1;
+ }
+
+ /*
* Some basic functions for raw data manipulation. "LE" means
* Little Endian.
*/
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 9392cf2..d8fef09 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -84,6 +84,8 @@
const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
const char CameraParameters::TRUE[] = "true";
const char CameraParameters::FALSE[] = "false";
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index c4f9e53..ccf98e5 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -184,6 +184,7 @@
identity = control->mIdentity;
}
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+ parcel->writeStrongBinder(NULL); // NULL ISurfaceTexture in this case.
parcel->writeInt32(identity);
return NO_ERROR;
}
@@ -192,7 +193,8 @@
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
- mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
+ sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));
+ mSurfaceData = new Surface(surface_control);
}
return mSurfaceData;
}
@@ -208,31 +210,58 @@
mSurface(surface->mSurface),
mIdentity(surface->mIdentity)
{
- init();
+ sp<ISurfaceTexture> st;
+ if (mSurface != NULL) {
+ st = mSurface->getSurfaceTexture();
+ }
+ init(st);
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
: SurfaceTextureClient()
{
- mSurface = interface_cast<ISurface>(ref);
+ mSurface = interface_cast<ISurface>(ref);
+ sp<IBinder> st_binder(parcel.readStrongBinder());
+ sp<ISurfaceTexture> st;
+ if (st_binder != NULL) {
+ st = interface_cast<ISurfaceTexture>(st_binder);
+ } else if (mSurface != NULL) {
+ st = mSurface->getSurfaceTexture();
+ }
+
mIdentity = parcel.readInt32();
- init();
+ init(st);
+}
+
+Surface::Surface(const sp<ISurfaceTexture>& st)
+ : SurfaceTextureClient(),
+ mSurface(NULL),
+ mIdentity(0)
+{
+ init(st);
}
status_t Surface::writeToParcel(
const sp<Surface>& surface, Parcel* parcel)
{
sp<ISurface> sur;
+ sp<ISurfaceTexture> st;
uint32_t identity = 0;
if (Surface::isValid(surface)) {
sur = surface->mSurface;
+ st = surface->getISurfaceTexture();
identity = surface->mIdentity;
- } else if (surface != 0 && surface->mSurface != 0) {
- LOGW("Parceling invalid surface with non-NULL ISurface as NULL: "
- "mSurface = %p, mIdentity = %d",
- surface->mSurface.get(), surface->mIdentity);
+ } else if (surface != 0 &&
+ (surface->mSurface != NULL ||
+ surface->getISurfaceTexture() != NULL)) {
+ LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: "
+ "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ",
+ surface->mSurface.get(), surface->getISurfaceTexture().get(),
+ surface->mIdentity);
}
- parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+
+ parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL);
+ parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL);
parcel->writeInt32(identity);
return NO_ERROR;
@@ -249,8 +278,8 @@
surface = new Surface(data, binder);
sCachedSurfaces.add(binder, surface);
}
- if (surface->mSurface == 0) {
- surface = 0;
+ if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
+ surface = 0;
}
cleanCachedSurfacesLocked();
return surface;
@@ -267,10 +296,9 @@
}
}
-void Surface::init()
+void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
{
- if (mSurface != NULL) {
- sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
+ if (mSurface != NULL || surfaceTexture != NULL) {
LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
if (surfaceTexture != NULL) {
setISurfaceTexture(surfaceTexture);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index c190195..16755ad 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -86,7 +86,6 @@
mClientBufferCount(0),
mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
mCurrentTexture(INVALID_BUFFER_SLOT),
- mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
mCurrentTransform(0),
mCurrentTimestamp(0),
mNextTransform(0),
@@ -197,11 +196,14 @@
status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
{
- Mutex::Autolock lock(mMutex);
- if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
- mDefaultWidth = w;
- mDefaultHeight = h;
+ if (!w || !h) {
+ LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", w, h);
+ return BAD_VALUE;
}
+
+ Mutex::Autolock lock(mMutex);
+ mDefaultWidth = w;
+ mDefaultHeight = h;
return OK;
}
@@ -651,12 +653,8 @@
LOGW("updateTexImage: clearing GL error: %#04x", error);
}
- GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format);
- if (target != mCurrentTextureTarget) {
- glDeleteTextures(1, &mTexName);
- }
- glBindTexture(target, mTexName);
- glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
bool failed = false;
while ((error = glGetError()) != GL_NO_ERROR) {
@@ -678,7 +676,6 @@
// Update the SurfaceTexture state.
mCurrentTexture = buf;
- mCurrentTextureTarget = target;
mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
mCurrentCrop = mSlots[buf].mCrop;
mCurrentTransform = mSlots[buf].mTransform;
@@ -692,7 +689,7 @@
mDequeueCondition.signal();
} else {
// We always bind the texture even if we don't update its contents.
- glBindTexture(mCurrentTextureTarget, mTexName);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
}
return OK;
@@ -717,20 +714,8 @@
return false;
}
-GLenum SurfaceTexture::getTextureTarget(uint32_t format)
-{
- GLenum target = GL_TEXTURE_2D;
-#if defined(GL_OES_EGL_image_external)
- if (isExternalFormat(format)) {
- target = GL_TEXTURE_EXTERNAL_OES;
- }
-#endif
- return target;
-}
-
GLenum SurfaceTexture::getCurrentTextureTarget() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureTarget;
+ return GL_TEXTURE_EXTERNAL_OES;
}
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
@@ -903,13 +888,9 @@
switch (what) {
case NATIVE_WINDOW_WIDTH:
value = mDefaultWidth;
- if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
- value = mCurrentTextureBuf->width;
break;
case NATIVE_WINDOW_HEIGHT:
value = mDefaultHeight;
- if (!mDefaultWidth && !mDefaultHeight && mCurrentTextureBuf!=0)
- value = mCurrentTextureBuf->height;
break;
case NATIVE_WINDOW_FORMAT:
value = mPixelFormat;
@@ -959,12 +940,12 @@
}
snprintf(buffer, SIZE,
- "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n"
+ "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
"%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
,
prefix, mCurrentCrop.left,
mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture, mCurrentTextureTarget,
+ mCurrentTransform, mCurrentTexture,
prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
mCurrentTransform, fifoSize, fifo.string()
);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index df0ad5a..e6837ea 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -52,9 +52,6 @@
mReqFormat = 0;
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
- mQueryWidth = 0;
- mQueryHeight = 0;
- mQueryFormat = 0;
mDefaultWidth = 0;
mDefaultHeight = 0;
mTransformHint = 0;
@@ -154,9 +151,6 @@
result);
return result;
}
- mQueryWidth = gbuf->width;
- mQueryHeight = gbuf->height;
- mQueryFormat = gbuf->format;
}
*buffer = gbuf.get();
return OK;
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 0fac6cd..44babcf 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -832,9 +832,7 @@
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) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) {
const int texWidth = 64;
const int texHeight = 66;
@@ -871,26 +869,24 @@
EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35));
EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(23, 65, 231, 35, 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, 228, 38, 38, 38));
+ EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231));
EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231));
- 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(37, 47, 231, 35, 231, 231));
+ EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35));
EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 25, 41, 41, 231, 231));
- EXPECT_TRUE(checkPixel(10, 9, 38, 38, 231, 231));
+ EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231));
EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231));
- EXPECT_TRUE(checkPixel(56, 31, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35));
EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231));
}
-// 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_TexturingFromCpuFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) {
const int texWidth = 64;
const int texHeight = 64;
@@ -944,9 +940,7 @@
EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35));
}
-// 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_TexturingFromGLFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) {
const int texWidth = 64;
const int texHeight = 64;
@@ -956,7 +950,7 @@
EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
mANW.get(), NULL);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+ ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
mEglContext));
@@ -980,6 +974,8 @@
eglSwapBuffers(mEglDisplay, stcEglSurface);
+ eglDestroySurface(mEglDisplay, stcEglSurface);
+
// Do the consumer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext));
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 7114b6a..c5858e9 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -173,13 +173,15 @@
gradientCache.clear();
// fall through
case kFlushMode_Moderate:
- layerCache.clear();
pathCache.clear();
roundRectShapeCache.clear();
circleShapeCache.clear();
ovalShapeCache.clear();
rectShapeCache.clear();
arcShapeCache.clear();
+ // fall through
+ case kFlushMode_Layers:
+ layerCache.clear();
break;
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 76dff4b..cdcbf21 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -101,7 +101,8 @@
public:
enum FlushMode {
- kFlushMode_Moderate = 0,
+ kFlushMode_Layers = 0,
+ kFlushMode_Moderate,
kFlushMode_Full
};
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 886c05c..88cfc5a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -74,12 +74,17 @@
if (logBuffer.isEmpty()) {
return;
}
- String8 cachesLog;
- Caches::getInstance().dumpMemoryUsage(cachesLog);
+
FILE *file = fdopen(fd, "a");
- fprintf(file, "\nCaches:\n%s", cachesLog.string());
+
fprintf(file, "\nRecent DisplayList operations\n");
logBuffer.outputCommands(file, OP_NAMES);
+
+ String8 cachesLog;
+ Caches::getInstance().dumpMemoryUsage(cachesLog);
+ fprintf(file, "\nCaches:\n%s", cachesLog.string());
+ fprintf(file, "\n");
+
fflush(file);
}
@@ -143,10 +148,10 @@
clearResources();
}
- size_t size = writer.size();
- void* buffer = sk_malloc_throw(size);
+ mSize = writer.size();
+ void* buffer = sk_malloc_throw(mSize);
writer.flatten(buffer);
- mReader.setMemory(buffer, size);
+ mReader.setMemory(buffer, mSize);
Caches& caches = Caches::getInstance();
@@ -188,6 +193,11 @@
}
void DisplayList::init() {
+ mSize = 0;
+}
+
+size_t DisplayList::getSize() {
+ return mSize;
}
/**
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 8157631..69e72a4 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -37,7 +37,7 @@
// Defines
///////////////////////////////////////////////////////////////////////////////
-#define MIN_WRITER_SIZE 16384
+#define MIN_WRITER_SIZE 4096
// Debug
#if DEBUG_DISPLAY_LIST
@@ -105,6 +105,8 @@
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
+ size_t getSize();
+
bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
void output(OpenGLRenderer& renderer, uint32_t level = 0);
@@ -203,6 +205,8 @@
Vector<SkiaShader*> mShaders;
mutable SkFlattenableReadBuffer mReader;
+
+ size_t mSize;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 4a40a63..996acd5 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -181,11 +181,8 @@
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
- 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);
+ texture->setFilter(GL_LINEAR, GL_LINEAR);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
}
}; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3c2d80d..dd75497 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -51,8 +51,6 @@
texture.width = layerWidth;
texture.height = layerHeight;
colorFilter = NULL;
- firstFilter = true;
- firstWrap = true;
}
~Layer() {
@@ -150,27 +148,11 @@
}
void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) {
- if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) {
- firstWrap = true;
- texture.setWrap(wrapS, wrapT);
- if (bindTexture) {
- glBindTexture(renderTarget, texture.id);
- }
- glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
- glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
- }
+ texture.setWrap(wrapS, wrapT, bindTexture, force, renderTarget);
}
void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) {
- if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) {
- firstFilter = false;
- texture.setFilter(min, mag);
- if (bindTexture) {
- glBindTexture(renderTarget, texture.id);
- }
- glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
- glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
- }
+ texture.setFilter(min, mag,bindTexture, force, renderTarget);
}
inline bool isCacheable() {
@@ -209,6 +191,10 @@
if (texture.id) glDeleteTextures(1, &texture.id);
}
+ inline void deleteFbo() {
+ if (fbo) glDeleteFramebuffers(1, &fbo);
+ }
+
inline void allocateTexture(GLenum format, GLenum storage) {
glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
}
@@ -296,8 +282,6 @@
*/
mat4 texTransform;
- bool firstFilter;
- bool firstWrap;
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 1a15e87..0af0177 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -68,7 +68,9 @@
void LayerCache::deleteLayer(Layer* layer) {
if (layer) {
+ LAYER_LOGD("Destroying layer %dx%d", layer->getWidth(), layer->getHeight());
mSize -= layer->getWidth() * layer->getHeight() * 4;
+ layer->deleteFbo();
layer->deleteTexture();
delete layer;
}
@@ -107,21 +109,25 @@
layer->generateTexture();
layer->bindTexture();
layer->setFilter(GL_NEAREST, GL_NEAREST);
- layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
#if DEBUG_LAYERS
- size_t size = mCache.size();
- for (size_t i = 0; i < size; i++) {
- const LayerEntry& entry = mCache.itemAt(i);
- LAYER_LOGD(" Layer size %dx%d", entry.mWidth, entry.mHeight);
- }
+ dump();
#endif
}
return layer;
}
+void LayerCache::dump() {
+ size_t size = mCache.size();
+ for (size_t i = 0; i < size; i++) {
+ const LayerEntry& entry = mCache.itemAt(i);
+ LAYER_LOGD(" Layer size %dx%d", entry.mWidth, entry.mHeight);
+ }
+}
+
bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
// TODO: We should be smarter and see if we have a texture of the appropriate
// size already in the cache, and reuse it instead of creating a new one
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 81b8bf3..a0eae59 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -101,6 +101,11 @@
*/
uint32_t getSize();
+ /**
+ * Prints out the content of the cache.
+ */
+ void dump();
+
private:
void deleteLayer(Layer* layer);
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 1fa343b..7e8c7fd 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -167,7 +167,7 @@
///////////////////////////////////////////////////////////////////////////////
Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
- LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
+ LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
GLuint fbo = Caches::getInstance().fboCache.get();
if (!fbo) {
@@ -288,16 +288,22 @@
void LayerRenderer::destroyLayer(Layer* layer) {
if (layer) {
- LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->getFbo());
+ LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
+ layer->getWidth(), layer->getHeight(), layer->getFbo());
if (layer->getFbo()) {
Caches::getInstance().fboCache.put(layer->getFbo());
}
if (!Caches::getInstance().layerCache.put(layer)) {
+ LAYER_RENDERER_LOGD(" Destroyed!");
layer->deleteTexture();
delete layer;
} else {
+ LAYER_RENDERER_LOGD(" Cached!");
+#if DEBUG_LAYER_RENDERER
+ Caches::getInstance().layerCache.dump();
+#endif
layer->region.clear();
}
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 85a9762..ed2fa3c 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1293,16 +1293,16 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
-
float x = left;
float y = top;
+ GLenum filter = GL_LINEAR;
bool ignoreTransform = false;
if (mSnapshot->transform->isPureTranslate()) {
x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
ignoreTransform = true;
+ filter = GL_NEAREST;
}
setupDraw();
@@ -1315,7 +1315,11 @@
setupDrawBlending(true, mode);
setupDrawProgram();
setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform);
+
setupDrawTexture(texture->id);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ texture->setFilter(filter, filter);
+
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
setupDrawShaderUniforms();
@@ -1379,7 +1383,9 @@
Texture* texture = mCaches.textureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
- setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+ texture->setFilter(GL_LINEAR, GL_LINEAR, true);
int alpha;
SkXfermode::Mode mode;
@@ -1462,7 +1468,7 @@
Texture* texture = mCaches.textureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
- setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
const float width = texture->width;
const float height = texture->height;
@@ -1483,11 +1489,19 @@
const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
+ GLenum filter = GL_NEAREST;
+ if (u1 > 0.0f || u2 < 1.0f || v1 > 0.0f || v2 < 1.0f) {
+ filter = GL_LINEAR;
+ }
+ texture->setFilter(filter, filter, true);
+
drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop),
texture->id, alpha / 255.0f, mode, texture->blend,
&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
GL_TRIANGLE_STRIP, gMeshCount, false, true);
} else {
+ texture->setFilter(GL_LINEAR, GL_LINEAR, true);
+
drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
GL_TRIANGLE_STRIP, gMeshCount);
@@ -1507,7 +1521,8 @@
Texture* texture = mCaches.textureCache.get(bitmap);
if (!texture) return;
const AutoTexture autoCleanup(texture);
- setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
+ texture->setFilter(GL_LINEAR, GL_LINEAR, true);
int alpha;
SkXfermode::Mode mode;
@@ -2411,16 +2426,18 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- setTextureWrapModes(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, true);
if (mSnapshot->transform->isPureTranslate()) {
const float x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
const float y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
+ texture->setFilter(GL_NEAREST, GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
alpha / 255.0f, mode, texture->blend, (GLvoid*) NULL,
(GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, false, true);
} else {
+ texture->setFilter(GL_LINEAR, GL_LINEAR, true);
drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
texture->blend, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
GL_TRIANGLE_STRIP, gMeshCount);
@@ -2550,22 +2567,5 @@
return resultMode;
}
-void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
- bool bound = false;
- if (wrapS != texture->wrapS) {
- glBindTexture(GL_TEXTURE_2D, texture->id);
- bound = true;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
- texture->wrapS = wrapS;
- }
- if (wrapT != texture->wrapT) {
- if (!bound) {
- glBindTexture(GL_TEXTURE_2D, texture->id);
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
- texture->wrapT = wrapT;
- }
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0a3d5090..fa893f0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -464,12 +464,6 @@
}
/**
- * Sets the wrap modes for the specified texture. The wrap modes are modified
- * only when needed.
- */
- inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT);
-
- /**
* Enable or disable blending as necessary. This function sets the appropriate
* blend function based on the specified xfermode.
*/
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 47049e2..923978f 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -68,7 +68,7 @@
#define MB(s) s * 1024 * 1024
#define DEFAULT_TEXTURE_CACHE_SIZE 24.0f
-#define DEFAULT_LAYER_CACHE_SIZE 24.0f
+#define DEFAULT_LAYER_CACHE_SIZE 16.0f
#define DEFAULT_PATH_CACHE_SIZE 4.0f
#define DEFAULT_SHAPE_CACHE_SIZE 1.0f
#define DEFAULT_PATCH_CACHE_SIZE 512
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index f4d9686..33953be 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -624,11 +624,8 @@
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels());
- 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);
+ texture->setFilter(GL_LINEAR, GL_LINEAR);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
}
}; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 8878c70..06382f2 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -77,14 +77,7 @@
void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
glBindTexture(GL_TEXTURE_2D, texture->id);
- if (wrapS != texture->wrapS) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
- texture->wrapS = wrapS;
- }
- if (wrapT != texture->wrapT) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
- texture->wrapT = wrapT;
- }
+ texture->setWrap(wrapS, wrapT);
}
void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
@@ -151,6 +144,12 @@
// Uniforms
bindTexture(texture, mWrapS, mWrapT);
+ // Assume linear here; we should really check the transform in
+ // ::updateTransforms() but we don't have the texture object
+ // available at that point. The optimization is not worth the
+ // effort for now.
+ texture->setFilter(GL_LINEAR, GL_LINEAR);
+
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 8f6f860..a3ee63b 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -137,11 +137,8 @@
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);
- 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);
+ texture->setFilter(GL_LINEAR, GL_LINEAR);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
if (size < mMaxSize) {
if (mDebugEnabled) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index c6ae326..48229b6 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -35,16 +35,45 @@
minFilter = GL_NEAREST;
magFilter = GL_NEAREST;
+
+ firstFilter = true;
+ firstWrap = true;
}
- void setWrap(GLenum wrapS, GLenum wrapT) {
- this->wrapS = wrapS;
- this->wrapT = wrapT;
+ void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false,
+ GLenum renderTarget = GL_TEXTURE_2D) {
+
+ if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) {
+ firstWrap = true;
+
+ this->wrapS = wrapS;
+ this->wrapT = wrapT;
+
+ if (bindTexture) {
+ glBindTexture(renderTarget, id);
+ }
+
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+ }
}
- void setFilter(GLenum min, GLenum mag) {
- minFilter = min;
- magFilter = mag;
+ void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false,
+ GLenum renderTarget = GL_TEXTURE_2D) {
+
+ if (firstFilter || force || min != minFilter || mag != magFilter) {
+ firstFilter = false;
+
+ minFilter = min;
+ magFilter = mag;
+
+ if (bindTexture) {
+ glBindTexture(renderTarget, id);
+ }
+
+ glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+ glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+ }
}
/**
@@ -87,6 +116,10 @@
*/
GLenum minFilter;
GLenum magFilter;
+
+private:
+ bool firstFilter;
+ bool firstWrap;
}; // struct Texture
class AutoTexture {
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 3752874..fbdbf92 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -165,7 +165,7 @@
void TextureCache::clear() {
mCache.clear();
- TEXTURE_LOGD("TextureCache:clear(), miSize = %d", mSize);
+ TEXTURE_LOGD("TextureCache:clear(), mSize = %d", mSize);
}
void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
@@ -219,11 +219,8 @@
break;
}
- 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);
+ texture->setFilter(GL_LINEAR, GL_LINEAR);
+ texture->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
}
void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
diff --git a/libs/rs/driver/rsdRuntimeStubs.cpp b/libs/rs/driver/rsdRuntimeStubs.cpp
index 2f9f410..d8050ac 100644
--- a/libs/rs/driver/rsdRuntimeStubs.cpp
+++ b/libs/rs/driver/rsdRuntimeStubs.cpp
@@ -365,24 +365,49 @@
return rsrGetAllocation(rsc, sc, ptr);
}
-static void SC_ForEach(Script *target,
- Allocation *in,
- Allocation *out,
- const void *usr,
- const RsScriptCall *call) {
+static void SC_ForEach_SAA(Script *target,
+ Allocation *in,
+ Allocation *out) {
+ GET_TLS();
+ rsrForEach(rsc, sc, target, in, out, NULL, 0, NULL);
+}
+
+static void SC_ForEach_SAAU(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr) {
GET_TLS();
rsrForEach(rsc, sc, target, in, out, usr, 0, NULL);
}
-static void SC_ForEach2(Script *target,
- Allocation *in,
- Allocation *out,
- const void *usr,
- const RsScriptCall *call) {
+static void SC_ForEach_SAAUS(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ const RsScriptCall *call) {
GET_TLS();
rsrForEach(rsc, sc, target, in, out, usr, 0, call);
}
+static void SC_ForEach_SAAUL(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ uint32_t usrLen) {
+ GET_TLS();
+ rsrForEach(rsc, sc, target, in, out, usr, usrLen, NULL);
+}
+
+static void SC_ForEach_SAAULS(Script *target,
+ Allocation *in,
+ Allocation *out,
+ const void *usr,
+ uint32_t usrLen,
+ const RsScriptCall *call) {
+ GET_TLS();
+ rsrForEach(rsc, sc, target, in, out, usr, usrLen, call);
+}
+
//////////////////////////////////////////////////////////////////////////////
@@ -648,8 +673,11 @@
{ "_Z19rsgClearDepthTargetv", (void *)&SC_ClearFrameBufferObjectDepthTarget, false },
{ "_Z24rsgClearAllRenderTargetsv", (void *)&SC_ClearFrameBufferObjectTargets, false },
- { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
- { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach2, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_", (void *)&SC_ForEach_SAA, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach_SAAU, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKvPK16rs_script_call_t", (void *)&SC_ForEach_SAAUS, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKvj", (void *)&SC_ForEach_SAAUL, false },
+ { "_Z9rsForEach9rs_script13rs_allocationS0_PKvjPK16rs_script_call_t", (void *)&SC_ForEach_SAAULS, false },
// time
{ "_Z6rsTimePi", (void *)&SC_Time, true },
diff --git a/libs/rs/scriptc/rs_core.rsh b/libs/rs/scriptc/rs_core.rsh
index 4768bbe..d939fb3 100644
--- a/libs/rs/scriptc/rs_core.rsh
+++ b/libs/rs/scriptc/rs_core.rsh
@@ -269,6 +269,7 @@
extern void __attribute__((overloadable))
rsMatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far);
+#if !defined(RS_VERSION) || (RS_VERSION < 14)
_RS_RUNTIME float4 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix4x4 *m, float4 in);
@@ -286,6 +287,25 @@
_RS_RUNTIME float2 __attribute__((overloadable))
rsMatrixMultiply(rs_matrix2x2 *m, float2 in);
+#else
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float4 in);
+
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float3 in);
+
+_RS_RUNTIME float4 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix4x4 *m, float2 in);
+
+_RS_RUNTIME float3 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix3x3 *m, float3 in);
+
+_RS_RUNTIME float3 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix3x3 *m, float2 in);
+
+_RS_RUNTIME float2 __attribute__((overloadable))
+rsMatrixMultiply(const rs_matrix2x2 *m, float2 in);
+#endif
// Returns true if the matrix was successfully inversed
extern bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m);
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index f38f72c..1d36cc6 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -249,15 +249,27 @@
uint32_t arrayEnd;
} rs_script_call_t;
-extern void __attribute__((overloadable))
- rsForEach(rs_script script, rs_allocation input,
- rs_allocation output, const void * usrData);
-
+#if !defined(RS_VERSION) || (RS_VERSION < 14)
extern void __attribute__((overloadable))
rsForEach(rs_script script, rs_allocation input,
rs_allocation output, const void * usrData,
const rs_script_call_t *);
+extern void __attribute__((overloadable))
+ rsForEach(rs_script script, rs_allocation input,
+ rs_allocation output, const void * usrData);
+#else
+extern void __attribute__((overloadable))
+ rsForEach(rs_script script, rs_allocation input, rs_allocation output);
+
+extern void __attribute__((overloadable))
+ rsForEach(rs_script script, rs_allocation input, rs_allocation output,
+ const void * usrData, size_t usrDataLen);
+
+extern void __attribute__((overloadable))
+ rsForEach(rs_script script, rs_allocation input, rs_allocation output,
+ const void * usrData, size_t usrDataLen, const rs_script_call_t *);
+#endif
/**
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index 536d1f0..121e013 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -19,6 +19,9 @@
typedef uint32_t uint;
typedef uint64_t ulong;
+typedef uint32_t size_t;
+typedef int32_t ssize_t;
+
typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_element;
typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_type;
typedef struct { const int* const p; } __attribute__((packed, aligned(4))) rs_allocation;
@@ -88,6 +91,8 @@
#define RS_PACKED __attribute__((packed, aligned(4)))
+#define NULL ((const void *)0)
+
typedef enum {
RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X = 0,
RS_ALLOCATION_CUBEMAP_FACE_NEGATIVE_X = 1,
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 693a32a..700b604 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -45,4 +45,4 @@
)
# Build the manual test programs.
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index cb6c246..6cf01c8 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4346,7 +4346,8 @@
| (0x0000ffff & (entryIndex));
resource_name resName;
if (!this->getResourceName(resID, &resName)) {
- return UNKNOWN_ERROR;
+ LOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
+ continue;
}
const String16 overlayType(resName.type, resName.typeLen);
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index 8726a53..b97f52f 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -8,7 +8,8 @@
ObbFile_test.cpp \
Looper_test.cpp \
String8_test.cpp \
- Unicode_test.cpp
+ Unicode_test.cpp \
+ ZipFileRO_test.cpp \
shared_libraries := \
libz \
diff --git a/libs/utils/tests/ZipFileRO_test.cpp b/libs/utils/tests/ZipFileRO_test.cpp
new file mode 100644
index 0000000..7a1d0bd
--- /dev/null
+++ b/libs/utils/tests/ZipFileRO_test.cpp
@@ -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.
+ */
+
+#define LOG_TAG "ZipFileRO_test"
+#include <utils/Log.h>
+#include <utils/ZipFileRO.h>
+
+#include <gtest/gtest.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+namespace android {
+
+class ZipFileROTest : public testing::Test {
+protected:
+ virtual void SetUp() {
+ }
+
+ virtual void TearDown() {
+ }
+};
+
+TEST_F(ZipFileROTest, ZipTimeConvertSuccess) {
+ struct tm t;
+
+ // 2011-06-29 14:40:40
+ long when = 0x3EDD7514;
+
+ ZipFileRO::zipTimeToTimespec(when, &t);
+
+ EXPECT_EQ(2011, t.tm_year + 1900)
+ << "Year was improperly converted.";
+
+ EXPECT_EQ(6, t.tm_mon)
+ << "Month was improperly converted.";
+
+ EXPECT_EQ(29, t.tm_mday)
+ << "Day was improperly converted.";
+
+ EXPECT_EQ(14, t.tm_hour)
+ << "Hour was improperly converted.";
+
+ EXPECT_EQ(40, t.tm_min)
+ << "Minute was improperly converted.";
+
+ EXPECT_EQ(40, t.tm_sec)
+ << "Second was improperly converted.";
+}
+
+}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 31e4631..8990fe5 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -54,7 +54,8 @@
/** Default audio channel mask */
public static final int CHANNEL_OUT_DEFAULT = 1;
- // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h
+ // Channel mask definitions below are translated to the native values defined in
+ // in /system/core/include/system/audio.h in the JNI code of AudioTrack
public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
public static final int CHANNEL_OUT_FRONT_CENTER = 0x10;
@@ -64,6 +65,25 @@
public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100;
public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200;
public static final int CHANNEL_OUT_BACK_CENTER = 0x400;
+ /** @hide */
+ public static final int CHANNEL_OUT_SIDE_LEFT = 0x800;
+ /** @hide */
+ public static final int CHANNEL_OUT_SIDE_RIGHT = 0x1000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_CENTER = 0x2000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_LEFT = 0x4000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_CENTER = 0x8000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_RIGHT = 0x10000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_LEFT = 0x20000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_CENTER = 0x40000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_RIGHT = 0x80000;
+
public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
@@ -75,6 +95,12 @@
public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
+ /** @hide */
+ public static final int CHANNEL_OUT_7POINT1_SURROUND = (
+ CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
+ CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+ CHANNEL_OUT_LOW_FREQUENCY);
public static final int CHANNEL_IN_DEFAULT = 1;
public static final int CHANNEL_IN_LEFT = 0x4;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 482b437..1bacdbb 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -611,7 +611,7 @@
* needed. Not calling this method when playing back a video will
* result in only the audio track being played.
*
- * Either a surface or surface texture must be set if a display or video sink
+ * Either a surface holder or surface must be set if a display or video sink
* is needed. Not calling this method or {@link #setTexture(SurfaceTexture)}
* when playing back a video will result in only the audio track being played.
*
@@ -630,6 +630,27 @@
}
/**
+ * Sets the {@link Surface} to be used as the sink for the video portion of
+ * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not
+ * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}.
+ * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set.
+ *
+ * @param surface The {@link Surface} to be used for the video portion of the media.
+ *
+ * @hide Pending review by API council.
+ */
+ public void setSurface(Surface surface) {
+ if (mScreenOnWhilePlaying && surface != null && mSurface != null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
+ }
+ mSurfaceHolder = null;
+ mSurface = surface;
+ mParcelSurfaceTexture = null; // TODO(tedbo): Remove.
+ _setVideoSurfaceOrSurfaceTexture();
+ updateSurfaceScreenOn();
+ }
+
+ /**
* Sets the {@link SurfaceTexture} to be used as the sink for the
* video portion of the media. Either a surface or surface texture
* must be set if a video sink is needed. The same surface texture
@@ -665,7 +686,7 @@
* @param pst The {@link ParcelSurfaceTexture} to be used as the sink for
* the video portion of the media.
*
- * @hide Pending review by API council.
+ * @hide Pending removal when there are no more callers.
*/
public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) {
if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) {
@@ -1000,8 +1021,8 @@
*/
public void setScreenOnWhilePlaying(boolean screenOn) {
if (mScreenOnWhilePlaying != screenOn) {
- if (screenOn && mParcelSurfaceTexture != null) {
- Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
+ if (screenOn && mSurfaceHolder == null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
}
mScreenOnWhilePlaying = screenOn;
updateSurfaceScreenOn();
@@ -1312,6 +1333,10 @@
*/
private static final int KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001;
+ // There are currently no defined keys usable from Java with get*Parameter.
+ // But if any keys are defined, the order must be kept in sync with include/media/mediaplayer.h.
+ // private static final int KEY_PARAMETER_... = ...;
+
/**
* Sets the parameter indicated by key.
* @param key key indicates the parameter to be set.
@@ -1331,7 +1356,9 @@
public boolean setParameter(int key, String value) {
Parcel p = Parcel.obtain();
p.writeString(value);
- return setParameter(key, p);
+ boolean ret = setParameter(key, p);
+ p.recycle();
+ return ret;
}
/**
@@ -1344,7 +1371,9 @@
public boolean setParameter(int key, int value) {
Parcel p = Parcel.obtain();
p.writeInt(value);
- return setParameter(key, p);
+ boolean ret = setParameter(key, p);
+ p.recycle();
+ return ret;
}
/**
@@ -1356,6 +1385,7 @@
/**
* Gets the value of the parameter indicated by key.
+ * The caller is responsible for recycling the returned parcel.
* @param key key indicates the parameter to get.
* @return value of the parameter.
* {@hide}
@@ -1375,7 +1405,9 @@
public String getStringParameter(int key) {
Parcel p = Parcel.obtain();
getParameter(key, p);
- return p.readString();
+ String ret = p.readString();
+ p.recycle();
+ return ret;
}
/**
@@ -1387,7 +1419,9 @@
public int getIntParameter(int key) {
Parcel p = Parcel.obtain();
getParameter(key, p);
- return p.readInt();
+ int ret = p.readInt();
+ p.recycle();
+ return ret;
}
/**
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 72069ac..8f5d0e5 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -176,6 +176,8 @@
public static final int DEFAULT = 0;
/** Camera video source */
public static final int CAMERA = 1;
+ /** @hide */
+ public static final int GRALLOC_BUFFER = 2;
}
/**
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index a8ac510..58f9432 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -872,10 +872,14 @@
values.put(Files.FileColumns.FORMAT, format);
}
// new file, insert it
- if (inserter != null) {
- result = inserter.insert(values);
- } else {
+ // We insert directories immediately to ensure they are in the database
+ // before the files they contain.
+ // Otherwise we can get duplicate directory entries in the database
+ // if one of the media FileInserters is flushed before the files table FileInserter
+ if (inserter == null || entry.mFormat == MtpConstants.FORMAT_ASSOCIATION) {
result = mMediaProvider.insert(tableUri, values);
+ } else {
+ result = inserter.insert(values);
}
if (result != null) {
diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java
new file mode 100644
index 0000000..7197dd2
--- /dev/null
+++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java
@@ -0,0 +1,67 @@
+/*
+ * 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.audiofx;
+
+/**
+ * Acoustic Echo Canceler (AEC).
+ * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the
+ * signal received from the remote party from the captured audio signal.
+ * <p>AEC is used by voice communication applications (voice chat, video conferencing, SIP calls)
+ * where the presence of echo with significant delay in the signal received from the remote party
+ * is highly disturbing. AEC is often used in conjunction with noise suppression (NS).
+ * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC
+ * engine in the audio capture path.
+ * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AEC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AcousticEchoCanceler extends AudioEffect {
+
+ private final static String TAG = "AcousticEchoCanceler";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an AEC</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public AcousticEchoCanceler(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_AEC, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 39c6d3e..3ac0104 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -66,6 +66,8 @@
private final static String TAG = "AudioEffect-JAVA";
+ // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h
+
/**
* The following UUIDs define effect types corresponding to standard audio
* effects whose implementation and interface conform to the OpenSL ES
@@ -105,6 +107,27 @@
.fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
/**
+ * UUID for Automatic Gain Control (AGC) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_AGC = UUID
+ .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
+
+ /**
+ * UUID for Acoustic Echo Canceler (AEC) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_AEC = UUID
+ .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
+
+ /**
+ * UUID for Noise Suppressor (NS) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_NS = UUID
+ .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
+
+ /**
* Null effect UUID. Used when the UUID for effect type of
* @hide
*/
@@ -180,7 +203,8 @@
* <ul>
* <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
* <li>uuid: UUID for this particular implementation</li>
- * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
+ * <li>connectMode: {@link #EFFECT_INSERT}, {@link #EFFECT_AUXILIARY} or
+ * {at_link #EFFECT_PRE_PROCESSING}</li>
* <li>name: human readable effect name</li>
* <li>implementor: human readable effect implementor name</li>
* </ul>
@@ -212,11 +236,13 @@
*/
public UUID uuid;
/**
- * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
- * category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied
+ * Indicates if the effect is of insert category {@link #EFFECT_INSERT}, auxiliary
+ * category {@link #EFFECT_AUXILIARY} or pre processing category
+ * {at_link #EFFECT_PRE_PROCESSING}. Insert effects (Typically an Equalizer) are applied
* to the entire audio source and usually not shared by several sources. Auxiliary effects
* (typically a reverberator) are applied to part of the signal (wet) and the effect output
* is added to the original signal (dry).
+ * Audio pre processing are applied to audio captured on a particular AudioRecord.
*/
public String connectMode;
/**
@@ -243,6 +269,12 @@
* attaching it to the MediaPlayer or AudioTrack.
*/
public static final String EFFECT_AUXILIARY = "Auxiliary";
+ /**
+ * Effect connection mode is pre processing.
+ * The audio pre processing effects are attached to an audio input (AudioRecord).
+ * @hide
+ */
+ public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
// --------------------------------------------------------------------------
// Member variables
@@ -410,6 +442,19 @@
return (Descriptor[]) native_query_effects();
}
+ /**
+ * Query all audio pre processing effects applied to the AudioRecord with the supplied
+ * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
+ * objects.
+ * @param audioSession system wide unique audio session identifier.
+ * @throws IllegalStateException
+ * @hide
+ */
+
+ static public Descriptor[] queryPreProcessings(int audioSession) {
+ return (Descriptor[]) native_query_pre_processing(audioSession);
+ }
+
// --------------------------------------------------------------------------
// Control methods
// --------------------
@@ -1155,6 +1200,8 @@
private static native Object[] native_query_effects();
+ private static native Object[] native_query_pre_processing(int audioSession);
+
// ---------------------------------------------------------
// Utility methods
// ------------------
diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java
new file mode 100644
index 0000000..44574f0
--- /dev/null
+++ b/media/java/android/media/audiofx/AutomaticGainControl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.audiofx;
+
+/**
+ * Automatic Gain Control (AGC).
+ * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the
+ * output of the captured signal by boosting or lowering input from the microphone to match a preset
+ * level so that that the output signal level is virtually constant.
+ * AGC can be used by applications where the input signal dynamic range is not important but where
+ * a constant strong capture level is desired.
+ * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC
+ * engine in the audio framework.
+ * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AGC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AutomaticGainControl extends AudioEffect {
+
+ private final static String TAG = "AutomaticGainControl";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an AutomaticGainControl as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an AGC</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The AutomaticGainControl
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public AutomaticGainControl(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_AGC, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java
new file mode 100644
index 0000000..4e7a8b6
--- /dev/null
+++ b/media/java/android/media/audiofx/NoiseSuppressor.java
@@ -0,0 +1,68 @@
+/*
+ * 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.audiofx;
+
+/**
+ * Noise Suppressor (NS).
+ * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the
+ * captured signal. The component of the signal considered as noise can be either stationary
+ * (car/airplane engine, AC system) or non-stationary (other peoples conversations, car horn) for
+ * more advanced implementations.
+ * <p>NS is mostly used by voice communication applications (voice chat, video conferencing,
+ * SIP calls).
+ * <p>An application creates a NoiseSuppressor object to instantiate and control an NS
+ * engine in the audio framework.
+ * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, NS can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class NoiseSuppressor extends AudioEffect {
+
+ private final static String TAG = "NoiseSuppressor";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an NoiseSuppressor as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an NS</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The NoiseSuppressor
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public NoiseSuppressor(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 922f7ed..e1d3219 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -127,7 +127,7 @@
return false;
}
-sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz)
+static sp<MediaRecorder> getMediaRecorder(JNIEnv* env, jobject thiz)
{
Mutex::Autolock l(sLock);
MediaRecorder* const p = (MediaRecorder*)env->GetIntField(thiz, fields.context);
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index e71e727..57cabe2 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -725,18 +725,22 @@
goto queryEffects_failure;
}
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ jdescConnect = env->NewStringUTF("Auxiliary");
+ } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT) {
+ jdescConnect = env->NewStringUTF("Insert");
+ } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+ jdescConnect = env->NewStringUTF("Pre Processing");
+ } else {
+ continue;
+ }
+
AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
jdescType = env->NewStringUTF(str);
AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
jdescUuid = env->NewStringUTF(str);
- if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- jdescConnect = env->NewStringUTF("Auxiliary");
- } else {
- jdescConnect = env->NewStringUTF("Insert");
- }
-
jdescName = env->NewStringUTF(desc.name);
jdescImplementor = env->NewStringUTF(desc.implementor);
@@ -771,6 +775,87 @@
}
+
+
+static jobjectArray
+android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz, jint audioSession)
+{
+ // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
+ // most devices to get all active audio pre processing on a given session.
+ static const uint32_t kDefaultNumEffects = 5;
+
+ effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects];
+ uint32_t numEffects = kDefaultNumEffects;
+
+ status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
+ descriptors,
+ &numEffects);
+ if ((status != NO_ERROR && status != NO_MEMORY) ||
+ numEffects == 0) {
+ delete[] descriptors;
+ return NULL;
+ }
+ if (status == NO_MEMORY) {
+ delete [] descriptors;
+ descriptors = new effect_descriptor_t[numEffects];
+ status = AudioEffect::queryDefaultPreProcessing(audioSession,
+ descriptors,
+ &numEffects);
+ }
+ if (status != NO_ERROR || numEffects == 0) {
+ delete[] descriptors;
+ return NULL;
+ }
+ LOGV("queryDefaultPreProcessing() got %d effects", numEffects);
+
+ jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
+ if (ret == NULL) {
+ delete[] descriptors;
+ return ret;
+ }
+
+ char str[EFFECT_STRING_LEN_MAX];
+ jstring jdescType;
+ jstring jdescUuid;
+ jstring jdescConnect;
+ jstring jdescName;
+ jstring jdescImplementor;
+ jobject jdesc;
+
+ for (uint32_t i = 0; i < numEffects; i++) {
+
+ AudioEffect::guidToString(&descriptors[i].type, str, EFFECT_STRING_LEN_MAX);
+ jdescType = env->NewStringUTF(str);
+ AudioEffect::guidToString(&descriptors[i].uuid, str, EFFECT_STRING_LEN_MAX);
+ jdescUuid = env->NewStringUTF(str);
+ jdescConnect = env->NewStringUTF("Pre Processing");
+ jdescName = env->NewStringUTF(descriptors[i].name);
+ jdescImplementor = env->NewStringUTF(descriptors[i].implementor);
+
+ jdesc = env->NewObject(fields.clazzDesc,
+ fields.midDescCstor,
+ jdescType,
+ jdescUuid,
+ jdescConnect,
+ jdescName,
+ jdescImplementor);
+ env->DeleteLocalRef(jdescType);
+ env->DeleteLocalRef(jdescUuid);
+ env->DeleteLocalRef(jdescConnect);
+ env->DeleteLocalRef(jdescName);
+ env->DeleteLocalRef(jdescImplementor);
+ if (jdesc == NULL) {
+ LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
+ env->DeleteLocalRef(ret);
+ return NULL;;
+ }
+
+ env->SetObjectArrayElement(ret, i, jdesc);
+ }
+
+ return ret;
+}
+
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
@@ -787,6 +872,8 @@
{"native_getParameter", "(I[BI[B)I", (void *)android_media_AudioEffect_native_getParameter},
{"native_command", "(II[BI[B)I", (void *)android_media_AudioEffect_native_command},
{"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects},
+ {"native_query_pre_processing", "(I)[Ljava/lang/Object;",
+ (void *)android_media_AudioEffect_native_queryPreProcessings},
};
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 69cfe8c..1af78e3 100755
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -42,11 +42,13 @@
$(TOP)/frameworks/media/libvideoeditor/vss/common/inc \
$(TOP)/frameworks/media/libvideoeditor/vss/mcs/inc \
$(TOP)/frameworks/media/libvideoeditor/vss/stagefrightshells/inc \
+ $(TOP)/frameworks/media/libvideoeditor/include \
$(TOP)/frameworks/media/libvideoeditor/lvpp \
$(TOP)/frameworks/media/libvideoeditor/osal/inc
LOCAL_SHARED_LIBRARIES := \
libcutils \
+ libdl \
libutils \
libandroid_runtime \
libnativehelper \
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
index 13f6350..ec8050f 100755
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ b/media/jni/mediaeditor/VideoEditorJava.cpp
@@ -25,11 +25,13 @@
void
-videoEditJava_checkAndThrowIllegalArgumentException(
+videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
bool* pResult,
JNIEnv* pEnv,
bool condition,
- const char* pMessage)
+ const char* pMessage,
+ const char* pFile,
+ int lineNo)
{
// Check if the previous action succeeded.
if (*pResult)
@@ -39,7 +41,8 @@
{
// Log the exception.
VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",\
- "videoEditJava_checkAndThrowIllegalArgumentException, %s", pMessage);
+ "videoEditJava_checkAndThrowIllegalArgumentException, %s (%s:%d)",
+ pMessage, pFile, lineNo);
// Reset the result flag.
(*pResult) = false;
@@ -51,11 +54,14 @@
}
void
-videoEditJava_checkAndThrowRuntimeException(
+videoEditJava_checkAndThrowRuntimeExceptionFunc(
bool* pResult,
JNIEnv* pEnv,
bool condition,
- M4OSA_ERR result)
+ M4OSA_ERR result,
+ const char* pFile,
+ int lineNo
+ )
{
const char* pMessage = NULL;
@@ -70,7 +76,8 @@
// Log the exception.
VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_checkAndThrowRuntimeException, %s", pMessage);
+ "videoEditJava_checkAndThrowRuntimeException, %s (%s:%d)",
+ pMessage, pFile, lineNo);
// Reset the result flag.
(*pResult) = false;
@@ -82,11 +89,14 @@
}
void
-videoEditJava_checkAndThrowIllegalStateException(
+videoEditJava_checkAndThrowIllegalStateExceptionFunc(
bool* pResult,
JNIEnv* pEnv,
bool condition,
- const char* pMessage)
+ const char* pMessage,
+ const char* pFile,
+ int lineNo
+ )
{
// Check if the previous action succeeded.
if (*pResult)
@@ -96,7 +106,8 @@
{
// Log the exception.
VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_checkAndThrowIllegalStateException, %s", pMessage);
+ "videoEditJava_checkAndThrowIllegalStateException, %s (%s:%d)",
+ pMessage, pFile, lineNo);
// Reset the result flag.
(*pResult) = false;
diff --git a/media/jni/mediaeditor/VideoEditorJava.h b/media/jni/mediaeditor/VideoEditorJava.h
index 9d7f096..0a2db08 100755
--- a/media/jni/mediaeditor/VideoEditorJava.h
+++ b/media/jni/mediaeditor/VideoEditorJava.h
@@ -351,26 +351,47 @@
jmethodID methodIds[];
} VideoEditJava_MethodIds;
-void
-videoEditJava_checkAndThrowIllegalArgumentException(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- const char* pMessage);
+#define videoEditJava_checkAndThrowIllegalArgumentException(\
+ a, b, c, d) videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(\
+ a, b, c, d, __FILE__, __LINE__)
+
+#define videoEditJava_checkAndThrowRuntimeException(\
+ a, b, c, d) videoEditJava_checkAndThrowRuntimeExceptionFunc(\
+ a, b, c, d, __FILE__, __LINE__)
+
+#define videoEditJava_checkAndThrowIllegalStateException(\
+ a, b, c, d) videoEditJava_checkAndThrowIllegalStateExceptionFunc(\
+ a, b, c, d, __FILE__, __LINE__)
void
-videoEditJava_checkAndThrowRuntimeException(
+videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
bool* pResult,
JNIEnv* pEnv,
bool condition,
- M4OSA_ERR result);
+ const char* pMessage,
+ const char* pFile,
+ int lineNo
+ );
void
-videoEditJava_checkAndThrowIllegalStateException(
+videoEditJava_checkAndThrowRuntimeExceptionFunc(
bool* pResult,
JNIEnv* pEnv,
bool condition,
- const char* pMessage);
+ M4OSA_ERR result,
+ const char* pFile,
+ int lineNo
+ );
+
+void
+videoEditJava_checkAndThrowIllegalStateExceptionFunc(
+ bool* pResult,
+ JNIEnv* pEnv,
+ bool condition,
+ const char* pMessage,
+ const char* pFile,
+ int lineNo
+ );
void
videoEditJava_getClass(
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 3919551..0633744 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -419,6 +419,15 @@
return af->getEffectDescriptor(uuid, descriptor);
}
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
// -------------------------------------------------------------------------
status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 1ec596e..16554c2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -590,7 +590,7 @@
audio_io_handle_t AudioRecord::getInput()
{
AutoMutex lock(mLock);
- return getInput_l();
+ return mInput;
}
// must be called with mLock held
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 49d410f..15f4be0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -53,6 +53,7 @@
UNREGISTER_EFFECT,
IS_STREAM_ACTIVE,
GET_DEVICES_FOR_STREAM,
+ QUERY_DEFAULT_PRE_PROCESSING
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -321,6 +322,31 @@
remote()->transact(IS_STREAM_ACTIVE, data, &reply);
return reply.readInt32();
}
+
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+ {
+ if (descriptors == NULL || count == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ data.writeInt32(*count);
+ status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ uint32_t retCount = reply.readInt32();
+ if (retCount != 0) {
+ uint32_t numDesc = (retCount < *count) ? retCount : *count;
+ reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+ }
+ *count = retCount;
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -559,6 +585,29 @@
return NO_ERROR;
} break;
+ case QUERY_DEFAULT_PRE_PROCESSING: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int audioSession = data.readInt32();
+ uint32_t count = data.readInt32();
+ uint32_t retCount = count;
+ effect_descriptor_t *descriptors =
+ (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+ status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+ reply->writeInt32(status);
+ if (status != NO_ERROR && status != NO_MEMORY) {
+ retCount = 0;
+ }
+ reply->writeInt32(retCount);
+ if (retCount) {
+ if (retCount < count) {
+ count = retCount;
+ }
+ reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+ }
+ delete[] descriptors;
+ return status;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 7e44c29..38e111e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -46,7 +46,6 @@
SET_AUDIO_ENCODER,
SET_OUTPUT_FILE_PATH,
SET_OUTPUT_FILE_FD,
- SET_OUTPUT_FILE_AUXILIARY_FD,
SET_VIDEO_SIZE,
SET_VIDEO_FRAMERATE,
SET_PARAMETERS,
@@ -177,15 +176,6 @@
return reply.readInt32();
}
- status_t setOutputFileAuxiliary(int fd) {
- LOGV("setOutputFileAuxiliary(%d)", fd);
- Parcel data, reply;
- data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
- data.writeFileDescriptor(fd);
- remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply);
- return reply.readInt32();
- }
-
status_t setVideoSize(int width, int height)
{
LOGV("setVideoSize(%dx%d)", width, height);
@@ -404,13 +394,6 @@
::close(fd);
return NO_ERROR;
} break;
- case SET_OUTPUT_FILE_AUXILIARY_FD: {
- LOGV("SET_OUTPUT_FILE_AUXILIARY_FD");
- CHECK_INTERFACE(IMediaRecorder, data, reply);
- int fd = dup(data.readFileDescriptor());
- reply->writeInt32(setOutputFileAuxiliary(fd));
- return NO_ERROR;
- } break;
case SET_VIDEO_SIZE: {
LOGV("SET_VIDEO_SIZE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index fab674c..11d281f 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -322,32 +322,6 @@
return ret;
}
-status_t MediaRecorder::setOutputFileAuxiliary(int fd)
-{
- LOGV("setOutputFileAuxiliary(%d)", fd);
- if(mMediaRecorder == NULL) {
- LOGE("media recorder is not initialized yet");
- return INVALID_OPERATION;
- }
- if (mIsAuxiliaryOutputFileSet) {
- LOGE("output file has already been set");
- return INVALID_OPERATION;
- }
- if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
- LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
- return INVALID_OPERATION;
- }
-
- status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd);
- if (OK != ret) {
- LOGV("setOutputFileAuxiliary failed: %d", ret);
- mCurrentState = MEDIA_RECORDER_ERROR;
- return ret;
- }
- mIsAuxiliaryOutputFileSet = true;
- return ret;
-}
-
status_t MediaRecorder::setVideoSize(int width, int height)
{
LOGV("setVideoSize(%d, %d)", width, height);
@@ -629,7 +603,6 @@
mIsAudioEncoderSet = false;
mIsVideoEncoderSet = false;
mIsOutputFileSet = false;
- mIsAuxiliaryOutputFileSet = false;
}
// Release should be OK in any state
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 905b885..6f80b35 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -178,17 +178,6 @@
return mRecorder->setOutputFile(fd, offset, length);
}
-status_t MediaRecorderClient::setOutputFileAuxiliary(int fd)
-{
- LOGV("setOutputFileAuxiliary(%d)", fd);
- Mutex::Autolock lock(mLock);
- if (mRecorder == NULL) {
- LOGE("recorder is not initialized");
- return NO_INIT;
- }
- return mRecorder->setOutputFileAuxiliary(fd);
-}
-
status_t MediaRecorderClient::setVideoSize(int width, int height)
{
LOGV("setVideoSize(%dx%d)", width, height);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index c87a3c0..c9ccf22 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -41,7 +41,6 @@
virtual status_t setOutputFile(const char* path);
virtual status_t setOutputFile(int fd, int64_t offset,
int64_t length);
- virtual status_t setOutputFileAuxiliary(int fd);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6427bb7..6fdb726 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -28,9 +28,7 @@
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/AACWriter.h>
#include <media/stagefright/CameraSource.h>
-#include <media/stagefright/VideoSourceDownSampler.h>
#include <media/stagefright/CameraSourceTimeLapse.h>
-#include <media/stagefright/MediaSourceSplitter.h>
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaDebug.h>
@@ -67,8 +65,8 @@
StagefrightRecorder::StagefrightRecorder()
- : mWriter(NULL), mWriterAux(NULL),
- mOutputFd(-1), mOutputFdAux(-1),
+ : mWriter(NULL),
+ mOutputFd(-1),
mAudioSource(AUDIO_SOURCE_CNT),
mVideoSource(VIDEO_SOURCE_LIST_END),
mStarted(false), mSurfaceMediaSource(NULL) {
@@ -259,24 +257,6 @@
return OK;
}
-status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) {
- LOGV("setOutputFileAuxiliary: %d", fd);
-
- if (fd < 0) {
- LOGE("Invalid file descriptor: %d", fd);
- return -EBADF;
- }
-
- mCaptureAuxVideo = true;
-
- if (mOutputFdAux >= 0) {
- ::close(mOutputFdAux);
- }
- mOutputFdAux = dup(fd);
-
- return OK;
-}
-
// Attempt to parse an int64 literal optionally surrounded by whitespace,
// returns true on success, false otherwise.
static bool safe_strtoi64(const char *s, int64_t *val) {
@@ -573,42 +553,6 @@
return OK;
}
-status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) {
- LOGV("setParamAuxVideoWidth : %d", width);
-
- if (width <= 0) {
- LOGE("Width (%d) is not positive", width);
- return BAD_VALUE;
- }
-
- mAuxVideoWidth = width;
- return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) {
- LOGV("setParamAuxVideoHeight : %d", height);
-
- if (height <= 0) {
- LOGE("Height (%d) is not positive", height);
- return BAD_VALUE;
- }
-
- mAuxVideoHeight = height;
- return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) {
- LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate);
-
- if (bitRate <= 0) {
- LOGE("Invalid video encoding bit rate: %d", bitRate);
- return BAD_VALUE;
- }
-
- mAuxVideoBitRate = bitRate;
- return OK;
-}
-
status_t StagefrightRecorder::setParamGeoDataLongitude(
int32_t longitudex10000) {
@@ -738,21 +682,6 @@
return setParamTimeBetweenTimeLapseFrameCapture(
1000LL * timeBetweenTimeLapseFrameCaptureMs);
}
- } else if (key == "video-aux-param-width") {
- int32_t auxWidth;
- if (safe_strtoi32(value.string(), &auxWidth)) {
- return setParamAuxVideoWidth(auxWidth);
- }
- } else if (key == "video-aux-param-height") {
- int32_t auxHeight;
- if (safe_strtoi32(value.string(), &auxHeight)) {
- return setParamAuxVideoHeight(auxHeight);
- }
- } else if (key == "video-aux-param-encoding-bitrate") {
- int32_t auxVideoBitRate;
- if (safe_strtoi32(value.string(), &auxVideoBitRate)) {
- return setParamAuxVideoEncodingBitRate(auxVideoBitRate);
- }
} else {
LOGE("setParameter: failed to find key %s", key.string());
}
@@ -1517,7 +1446,6 @@
}
status_t StagefrightRecorder::setupMPEG4Recording(
- bool useSplitCameraSource,
int outputFd,
int32_t videoWidth, int32_t videoHeight,
int32_t videoBitRate,
@@ -1531,28 +1459,7 @@
if (mVideoSource < VIDEO_SOURCE_LIST_END) {
sp<MediaSource> mediaSource;
- if (useSplitCameraSource) {
- // TODO: Check if there is a better way to handle this
- if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
- LOGE("Cannot use split camera when encoding frames");
- return INVALID_OPERATION;
- }
- LOGV("Using Split camera source");
- mediaSource = mCameraSourceSplitter->createClient();
- } else {
- err = setupMediaSource(&mediaSource);
- }
-
- if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) {
- // TODO: Might be able to handle downsampling even if using GRAlloc
- if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
- LOGE("Cannot change size or Downsample when encoding frames");
- return INVALID_OPERATION;
- }
- // Use downsampling from the original source.
- mediaSource =
- new VideoSourceDownSampler(mediaSource, videoWidth, videoHeight);
- }
+ err = setupMediaSource(&mediaSource);
if (err != OK) {
return err;
}
@@ -1620,24 +1527,8 @@
}
status_t StagefrightRecorder::startMPEG4Recording() {
- if (mCaptureAuxVideo) {
- if (!mCaptureTimeLapse) {
- LOGE("Auxiliary video can be captured only in time lapse mode");
- return UNKNOWN_ERROR;
- }
- LOGV("Creating MediaSourceSplitter");
- sp<CameraSource> cameraSource;
- status_t err = setupCameraSource(&cameraSource);
- if (err != OK) {
- return err;
- }
- mCameraSourceSplitter = new MediaSourceSplitter(cameraSource);
- } else {
- mCameraSourceSplitter = NULL;
- }
-
int32_t totalBitRate;
- status_t err = setupMPEG4Recording(mCaptureAuxVideo,
+ status_t err = setupMPEG4Recording(
mOutputFd, mVideoWidth, mVideoHeight,
mVideoBitRate, &totalBitRate, &mWriter);
if (err != OK) {
@@ -1653,33 +1544,6 @@
return err;
}
- if (mCaptureAuxVideo) {
- CHECK(mOutputFdAux >= 0);
- if (mWriterAux != NULL) {
- LOGE("Auxiliary File writer is not avaialble");
- return UNKNOWN_ERROR;
- }
- if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) ||
- ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) {
- LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)",
- mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight);
- return UNKNOWN_ERROR;
- }
-
- int32_t totalBitrateAux;
- err = setupMPEG4Recording(mCaptureAuxVideo,
- mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight,
- mAuxVideoBitRate, &totalBitrateAux, &mWriterAux);
- if (err != OK) {
- return err;
- }
-
- sp<MetaData> metaAux = new MetaData;
- setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux);
-
- return mWriterAux->start(metaAux.get());
- }
-
return OK;
}
@@ -1690,13 +1554,6 @@
}
mWriter->pause();
- if (mCaptureAuxVideo) {
- if (mWriterAux == NULL) {
- return UNKNOWN_ERROR;
- }
- mWriterAux->pause();
- }
-
if (mStarted) {
mStarted = false;
@@ -1724,13 +1581,6 @@
mCameraSourceTimeLapse = NULL;
}
- if (mCaptureAuxVideo) {
- if (mWriterAux != NULL) {
- mWriterAux->stop();
- mWriterAux.clear();
- }
- }
-
if (mWriter != NULL) {
err = mWriter->stop();
mWriter.clear();
@@ -1741,13 +1591,6 @@
mOutputFd = -1;
}
- if (mCaptureAuxVideo) {
- if (mOutputFdAux >= 0) {
- ::close(mOutputFdAux);
- mOutputFdAux = -1;
- }
- }
-
if (mStarted) {
mStarted = false;
@@ -1787,11 +1630,8 @@
mVideoEncoder = VIDEO_ENCODER_H263;
mVideoWidth = 176;
mVideoHeight = 144;
- mAuxVideoWidth = 176;
- mAuxVideoHeight = 144;
mFrameRate = -1;
mVideoBitRate = 192000;
- mAuxVideoBitRate = 192000;
mSampleRate = 8000;
mAudioChannels = 1;
mAudioBitRate = 12200;
@@ -1811,8 +1651,6 @@
mTrackEveryTimeDurationUs = 0;
mCaptureTimeLapse = false;
mTimeBetweenTimeLapseFrameCaptureUs = -1;
- mCaptureAuxVideo = false;
- mCameraSourceSplitter = NULL;
mCameraSourceTimeLapse = NULL;
mIsMetaDataStoredInVideoBuffers = false;
mEncoderProfiles = MediaProfiles::getInstance();
@@ -1821,7 +1659,6 @@
mLongitudex10000 = -3600000;
mOutputFd = -1;
- mOutputFdAux = -1;
return OK;
}
@@ -1858,8 +1695,6 @@
snprintf(buffer, SIZE, " Recorder: %p\n", this);
snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd);
result.append(buffer);
- snprintf(buffer, SIZE, " Output file Auxiliary (fd %d):\n", mOutputFdAux);
- result.append(buffer);
snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat);
result.append(buffer);
snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes);
@@ -1904,14 +1739,10 @@
result.append(buffer);
snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
result.append(buffer);
- snprintf(buffer, SIZE, " Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight);
- result.append(buffer);
snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate);
result.append(buffer);
snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate);
result.append(buffer);
- snprintf(buffer, SIZE, " Aux Bit rate (bps): %d\n", mAuxVideoBitRate);
- result.append(buffer);
::write(fd, result.string(), result.size());
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 1618b92..5c5f05c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -30,7 +30,6 @@
class ICameraRecordingProxy;
class CameraSource;
class CameraSourceTimeLapse;
-class MediaSourceSplitter;
struct MediaSource;
struct MediaWriter;
class MetaData;
@@ -55,7 +54,6 @@
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);
- virtual status_t setOutputFileAuxiliary(int fd);
virtual status_t setParameters(const String8& params);
virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
virtual status_t prepare();
@@ -74,8 +72,8 @@
sp<ICameraRecordingProxy> mCameraProxy;
sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
- sp<MediaWriter> mWriter, mWriterAux;
- int mOutputFd, mOutputFdAux;
+ sp<MediaWriter> mWriter;
+ int mOutputFd;
sp<AudioSource> mAudioSourceNode;
audio_source_t mAudioSource;
@@ -85,9 +83,8 @@
video_encoder mVideoEncoder;
bool mUse64BitFileOffset;
int32_t mVideoWidth, mVideoHeight;
- int32_t mAuxVideoWidth, mAuxVideoHeight;
int32_t mFrameRate;
- int32_t mVideoBitRate, mAuxVideoBitRate;
+ int32_t mVideoBitRate;
int32_t mAudioBitRate;
int32_t mAudioChannels;
int32_t mSampleRate;
@@ -109,8 +106,6 @@
bool mCaptureTimeLapse;
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
- bool mCaptureAuxVideo;
- sp<MediaSourceSplitter> mCameraSourceSplitter;
sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
@@ -127,7 +122,6 @@
sp<SurfaceMediaSource> mSurfaceMediaSource;
status_t setupMPEG4Recording(
- bool useSplitCameraSource,
int outputFd,
int32_t videoWidth, int32_t videoHeight,
int32_t videoBitRate,
@@ -166,9 +160,6 @@
status_t setParamAudioTimeScale(int32_t timeScale);
status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
- status_t setParamAuxVideoHeight(int32_t height);
- status_t setParamAuxVideoWidth(int32_t width);
- status_t setParamAuxVideoEncodingBitRate(int32_t bitRate);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
status_t setParamVideoIFramesInterval(int32_t seconds);
status_t setParamVideoEncoderProfile(int32_t profile);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 0098537..67f6c79 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2238,7 +2238,22 @@
}
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
- return OK;
+ switch (key) {
+ case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
+ {
+ int32_t channelCount;
+ if (mAudioTrack == 0 ||
+ !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
+ channelCount = 0;
+ }
+ reply->writeInt32(channelCount);
+ }
+ return OK;
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
}
bool AwesomePlayer::isStreamingHTTP() const {
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index fe78c46..1ba79e5 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -24,15 +24,10 @@
#include <media/stagefright/CameraSourceTimeLapse.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MetaData.h>
-#include <media/stagefright/YUVImage.h>
-#include <media/stagefright/YUVCanvas.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
-#include <ui/Rect.h>
#include <utils/String8.h>
#include <utils/Vector.h>
-#include "OMX_Video.h"
-#include <limits.h>
namespace android {
@@ -74,20 +69,14 @@
mLastTimeLapseFrameRealTimestampUs(0),
mSkipCurrentFrame(false) {
- LOGD("starting time lapse mode: %lld us", mTimeBetweenTimeLapseFrameCaptureUs);
+ LOGD("starting time lapse mode: %lld us",
+ mTimeBetweenTimeLapseFrameCaptureUs);
+
mVideoWidth = videoSize.width;
mVideoHeight = videoSize.height;
- if (trySettingVideoSize(videoSize.width, videoSize.height)) {
- mUseStillCameraForTimeLapse = false;
- } else {
- // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
- // than the fastest rate at which the still camera can take pictures.
- mUseStillCameraForTimeLapse = true;
- CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height));
- mNeedCropping = computeCropRectangleOffset();
- mMeta->setInt32(kKeyWidth, videoSize.width);
- mMeta->setInt32(kKeyHeight, videoSize.height);
+ if (!trySettingVideoSize(videoSize.width, videoSize.height)) {
+ mInitCheck = NO_INIT;
}
// Initialize quick stop variables.
@@ -101,24 +90,22 @@
}
void CameraSourceTimeLapse::startQuickReadReturns() {
+ LOGV("startQuickReadReturns");
Mutex::Autolock autoLock(mQuickStopLock);
- LOGV("Enabling quick read returns");
// Enable quick stop mode.
mQuickStop = true;
- if (mUseStillCameraForTimeLapse) {
- // wake up the thread right away.
- mTakePictureCondition.signal();
- } else {
- // Force dataCallbackTimestamp() coming from the video camera to not skip the
- // next frame as we want read() to get a get a frame right away.
- mForceRead = true;
- }
+ // Force dataCallbackTimestamp() coming from the video camera to
+ // not skip the next frame as we want read() to get a get a frame
+ // right away.
+ mForceRead = true;
}
-bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) {
- LOGV("trySettingVideoSize: %dx%d", width, height);
+bool CameraSourceTimeLapse::trySettingVideoSize(
+ int32_t width, int32_t height) {
+
+ LOGV("trySettingVideoSize");
int64_t token = IPCThreadState::self()->clearCallingIdentity();
String8 s = mCamera->getParameters();
@@ -162,53 +149,8 @@
return isSuccessful;
}
-bool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
- LOGV("setPictureSizeToClosestSupported: %dx%d", width, height);
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- String8 s = mCamera->getParameters();
- IPCThreadState::self()->restoreCallingIdentity(token);
-
- CameraParameters params(s);
- Vector<Size> supportedSizes;
- params.getSupportedPictureSizes(supportedSizes);
-
- int32_t minPictureSize = INT_MAX;
- for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
- int32_t pictureWidth = supportedSizes[i].width;
- int32_t pictureHeight = supportedSizes[i].height;
-
- if ((pictureWidth >= width) && (pictureHeight >= height)) {
- int32_t pictureSize = pictureWidth*pictureHeight;
- if (pictureSize < minPictureSize) {
- minPictureSize = pictureSize;
- mPictureWidth = pictureWidth;
- mPictureHeight = pictureHeight;
- }
- }
- }
- LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
- return (minPictureSize != INT_MAX);
-}
-
-bool CameraSourceTimeLapse::computeCropRectangleOffset() {
- if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
- return false;
- }
-
- CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
-
- int32_t widthDifference = mPictureWidth - mVideoWidth;
- int32_t heightDifference = mPictureHeight - mVideoHeight;
-
- mCropRectStartX = widthDifference/2;
- mCropRectStartY = heightDifference/2;
-
- LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
-
- return true;
-}
-
void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
+ LOGV("signalBufferReturned");
Mutex::Autolock autoLock(mQuickStopLock);
if (mQuickStop && (buffer == mLastReadBufferCopy)) {
buffer->setObserver(NULL);
@@ -218,7 +160,12 @@
}
}
-void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) {
+void createMediaBufferCopy(
+ const MediaBuffer& sourceBuffer,
+ int64_t frameTime,
+ MediaBuffer **newBuffer) {
+
+ LOGV("createMediaBufferCopy");
size_t sourceSize = sourceBuffer.size();
void* sourcePointer = sourceBuffer.data();
@@ -229,6 +176,7 @@
}
void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
+ LOGV("fillLastReadBufferCopy");
int64_t frameTime;
CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
@@ -238,11 +186,12 @@
status_t CameraSourceTimeLapse::read(
MediaBuffer **buffer, const ReadOptions *options) {
+ LOGV("read");
if (mLastReadBufferCopy == NULL) {
mLastReadStatus = CameraSource::read(buffer, options);
- // mQuickStop may have turned to true while read was blocked. Make a copy of
- // the buffer in that case.
+ // mQuickStop may have turned to true while read was blocked.
+ // Make a copy of the buffer in that case.
Mutex::Autolock autoLock(mQuickStopLock);
if (mQuickStop && *buffer) {
fillLastReadBufferCopy(**buffer);
@@ -255,105 +204,19 @@
}
}
-// static
-void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
- CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
- source->threadTimeLapseEntry();
- return NULL;
-}
-
-void CameraSourceTimeLapse::threadTimeLapseEntry() {
- while (mStarted) {
- {
- Mutex::Autolock autoLock(mCameraIdleLock);
- if (!mCameraIdle) {
- mCameraIdleCondition.wait(mCameraIdleLock);
- }
- CHECK(mCameraIdle);
- mCameraIdle = false;
- }
-
- // Even if mQuickStop == true we need to take one more picture
- // as a read() may be blocked, waiting for a frame to get available.
- // After this takePicture, if mQuickStop == true, we can safely exit
- // this thread as read() will make a copy of this last frame and keep
- // returning it in the quick stop mode.
- Mutex::Autolock autoLock(mQuickStopLock);
- CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
- if (mQuickStop) {
- LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
- return;
- }
- mTakePictureCondition.waitRelative(mQuickStopLock,
- mTimeBetweenTimeLapseFrameCaptureUs * 1000);
- }
- LOGV("threadTimeLapseEntry: Exiting due to mStarted = false");
-}
-
-void CameraSourceTimeLapse::startCameraRecording() {
- if (mUseStillCameraForTimeLapse) {
- LOGV("start time lapse recording using still camera");
-
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- String8 s = mCamera->getParameters();
-
- CameraParameters params(s);
- params.setPictureSize(mPictureWidth, mPictureHeight);
- mCamera->setParameters(params.flatten());
- mCameraIdle = true;
- mStopWaitingForIdleCamera = false;
-
- // disable shutter sound and play the recording sound.
- mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
- mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
- IPCThreadState::self()->restoreCallingIdentity(token);
-
- // create a thread which takes pictures in a loop
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
- pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
- pthread_attr_destroy(&attr);
- } else {
- LOGV("start time lapse recording using video camera");
- CameraSource::startCameraRecording();
- }
-}
-
void CameraSourceTimeLapse::stopCameraRecording() {
- if (mUseStillCameraForTimeLapse) {
- void *dummy;
- pthread_join(mThreadTimeLapse, &dummy);
-
- // Last takePicture may still be underway. Wait for the camera to get
- // idle.
- Mutex::Autolock autoLock(mCameraIdleLock);
- mStopWaitingForIdleCamera = true;
- if (!mCameraIdle) {
- mCameraIdleCondition.wait(mCameraIdleLock);
- }
- CHECK(mCameraIdle);
- mCamera->setListener(NULL);
-
- // play the recording sound.
- mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
- } else {
- CameraSource::stopCameraRecording();
- }
+ LOGV("stopCameraRecording");
+ CameraSource::stopCameraRecording();
if (mLastReadBufferCopy) {
mLastReadBufferCopy->release();
mLastReadBufferCopy = NULL;
}
}
-void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (!mUseStillCameraForTimeLapse) {
- CameraSource::releaseRecordingFrame(frame);
- }
-}
+sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
+ const sp<IMemory> &source_data) {
-sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
+ LOGV("createIMemoryCopy");
size_t source_size = source_data->size();
void* source_pointer = source_data->pointer();
@@ -363,102 +226,8 @@
return newMemory;
}
-// Allocates IMemory of final type MemoryBase with the given size.
-sp<IMemory> allocateIMemory(size_t size) {
- sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
- sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
- return newMemory;
-}
-
-// static
-void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
- CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
- source->threadStartPreview();
- return NULL;
-}
-
-void CameraSourceTimeLapse::threadStartPreview() {
- CHECK_EQ(OK, mCamera->startPreview());
- Mutex::Autolock autoLock(mCameraIdleLock);
- mCameraIdle = true;
- mCameraIdleCondition.signal();
-}
-
-void CameraSourceTimeLapse::restartPreview() {
- // Start this in a different thread, so that the dataCallback can return
- LOGV("restartPreview");
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- pthread_t threadPreview;
- pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
- pthread_attr_destroy(&attr);
-}
-
-sp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
- // find the YUV format
- int32_t srcFormat;
- CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
- YUVImage::YUVFormat yuvFormat;
- if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
- yuvFormat = YUVImage::YUV420SemiPlanar;
- } else {
- CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar);
- yuvFormat = YUVImage::YUV420Planar;
- }
-
- // allocate memory for cropped image and setup a canvas using it.
- sp<IMemory> croppedImageMemory = allocateIMemory(
- YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
- YUVImage yuvImageCropped(yuvFormat,
- mVideoWidth, mVideoHeight,
- (uint8_t *)croppedImageMemory->pointer());
- YUVCanvas yuvCanvasCrop(yuvImageCropped);
-
- YUVImage yuvImageSource(yuvFormat,
- mPictureWidth, mPictureHeight,
- (uint8_t *)source_data->pointer());
- yuvCanvasCrop.CopyImageRect(
- Rect(mCropRectStartX, mCropRectStartY,
- mCropRectStartX + mVideoWidth,
- mCropRectStartY + mVideoHeight),
- 0, 0,
- yuvImageSource);
-
- return croppedImageMemory;
-}
-
-void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
- if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
- // takePicture will complete after this callback, so restart preview.
- restartPreview();
- return;
- }
- if (msgType != CAMERA_MSG_RAW_IMAGE) {
- return;
- }
-
- LOGV("dataCallback for timelapse still frame");
- CHECK_EQ(true, mUseStillCameraForTimeLapse);
-
- int64_t timestampUs;
- if (mNumFramesReceived == 0) {
- timestampUs = mStartTimeUs;
- } else {
- timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- }
-
- if (mNeedCropping) {
- sp<IMemory> croppedImageData = cropYUVImage(data);
- dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
- } else {
- sp<IMemory> dataCopy = createIMemoryCopy(data);
- dataCallbackTimestamp(timestampUs, msgType, dataCopy);
- }
-}
-
bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
+ LOGV("skipCurrentFrame");
if (mSkipCurrentFrame) {
mSkipCurrentFrame = false;
return true;
@@ -468,72 +237,58 @@
}
bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
- if (!mUseStillCameraForTimeLapse) {
- if (mLastTimeLapseFrameRealTimestampUs == 0) {
- // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
- // to current time (timestampUs) and save frame data.
- LOGV("dataCallbackTimestamp timelapse: initial frame");
+ LOGV("skipFrameAndModifyTimeStamp");
+ if (mLastTimeLapseFrameRealTimestampUs == 0) {
+ // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
+ // to current time (timestampUs) and save frame data.
+ LOGV("dataCallbackTimestamp timelapse: initial frame");
- mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ return false;
+ }
+
+ {
+ Mutex::Autolock autoLock(mQuickStopLock);
+
+ // mForceRead may be set to true by startQuickReadReturns(). In that
+ // case don't skip this frame.
+ if (mForceRead) {
+ LOGV("dataCallbackTimestamp timelapse: forced read");
+ mForceRead = false;
+ *timestampUs =
+ mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
return false;
}
+ }
- {
- Mutex::Autolock autoLock(mQuickStopLock);
+ // Workaround to bypass the first 2 input frames for skipping.
+ // The first 2 output frames from the encoder are: decoder specific info and
+ // the compressed video frame data for the first input video frame.
+ if (mNumFramesEncoded >= 1 && *timestampUs <
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
+ // Skip all frames from last encoded frame until
+ // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+ // Tell the camera to release its recording frame and return.
+ LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
+ return true;
+ } else {
+ // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
+ // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
+ // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
+ // of the last encoded frame's time stamp.
+ LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
- // mForceRead may be set to true by startQuickReadReturns(). In that
- // case don't skip this frame.
- if (mForceRead) {
- LOGV("dataCallbackTimestamp timelapse: forced read");
- mForceRead = false;
- *timestampUs =
- mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- return false;
- }
- }
-
- // Workaround to bypass the first 2 input frames for skipping.
- // The first 2 output frames from the encoder are: decoder specific info and
- // the compressed video frame data for the first input video frame.
- if (mNumFramesEncoded >= 1 && *timestampUs <
- (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
- // Skip all frames from last encoded frame until
- // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
- // Tell the camera to release its recording frame and return.
- LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
- return true;
- } else {
- // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
- // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
- // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
- // of the last encoded frame's time stamp.
- LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
-
- mLastTimeLapseFrameRealTimestampUs = *timestampUs;
- *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- return false;
- }
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+ return false;
}
return false;
}
void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
const sp<IMemory> &data) {
- if (!mUseStillCameraForTimeLapse) {
- mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs);
- } else {
- Mutex::Autolock autoLock(mCameraIdleLock);
- // If we are using the still camera and stop() has been called, it may
- // be waiting for the camera to get idle. In that case return
- // immediately. Calling CameraSource::dataCallbackTimestamp() will lead
- // to a deadlock since it tries to access CameraSource::mLock which in
- // this case is held by CameraSource::stop() currently waiting for the
- // camera to get idle. And camera will not get idle until this call
- // returns.
- if (mStopWaitingForIdleCamera) {
- return;
- }
- }
+ LOGV("dataCallbackTimestamp");
+ mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs);
CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
}
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index ff4b08f..3d8c56a 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/openmax/OMX_IVCommon.h>
+#include <media/stagefright/MetadataBufferType.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
@@ -710,9 +711,9 @@
mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
- // Pass the data to the MediaBuffer
- // TODO: Change later to pass in only the metadata
- *buffer = new MediaBuffer(mCurrentBuf);
+ // Pass the data to the MediaBuffer. Pass in only the metadata
+ passMetadataBufferLocked(buffer);
+
(*buffer)->setObserver(this);
(*buffer)->add_ref();
(*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
@@ -720,6 +721,34 @@
return OK;
}
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+ LOGV("passMetadataBuffer");
+ // MediaBuffer allocates and owns this data
+ MediaBuffer *tempBuffer =
+ new MediaBuffer(4 + sizeof(buffer_handle_t));
+ char *data = (char *)tempBuffer->data();
+ if (data == NULL) {
+ LOGE("Cannot allocate memory for passing buffer metadata!");
+ return;
+ }
+ OMX_U32 type = kMetadataBufferTypeGrallocSource;
+ memcpy(data, &type, 4);
+ memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+ *buffer = tempBuffer;
+}
+
+
void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
LOGV("signalBufferReturned");
@@ -727,14 +756,13 @@
Mutex::Autolock autoLock(mMutex);
if (!mStarted) {
- LOGV("started = false. Nothing to do");
+ LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
return;
}
for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
- if (mSlots[*it].mGraphicBuffer == buffer->graphicBuffer()) {
- LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d",
- *it, mQueue.size()-1);
+ CHECK(mSlots[*it].mGraphicBuffer != NULL);
+ if (checkBufferMatchesSlot(*it, buffer)) {
mSlots[*it].mBufferState = BufferSlot::FREE;
mQueue.erase(it);
buffer->setObserver(0);
@@ -751,6 +779,14 @@
}
}
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+ LOGV("Check if Buffer matches slot");
+ // need to convert to char* for pointer arithmetic and then
+ // copy the byte stream into our handle
+ buffer_handle_t bufferHandle ;
+ memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+ return mSlots[slot].mGraphicBuffer->handle == bufferHandle;
+}
} // end of namespace android
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index f4b3668..eb10ab7 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -25,6 +25,7 @@
#include "android/net/android_network_library_impl.h"
#include "base/threading/thread.h"
#include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth_handler_factory.h"
@@ -140,6 +141,8 @@
network_delegate(),
net_log(),
NULL)); // backend_factory
+
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
}
const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 504d470..c8278ab 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -57,6 +57,9 @@
typedef OMXPluginBase *(*CreateOMXPluginFunc)();
CreateOMXPluginFunc createOMXPlugin =
(CreateOMXPluginFunc)dlsym(
+ mVendorLibHandle, "createOMXPlugin");
+ if (!createOMXPlugin)
+ createOMXPlugin = (CreateOMXPluginFunc)dlsym(
mVendorLibHandle, "_ZN7android15createOMXPluginEv");
if (createOMXPlugin) {
@@ -96,11 +99,19 @@
void OMXMaster::clearPlugins() {
Mutex::Autolock autoLock(mLock);
+ typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
+ DestroyOMXPluginFunc destroyOMXPlugin =
+ (DestroyOMXPluginFunc)dlsym(
+ mVendorLibHandle, "destroyOMXPlugin");
+
mPluginByComponentName.clear();
for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
- it != mPlugins.end(); ++it) {
- delete *it;
+ it != mPlugins.end(); ++it) {
+ if (destroyOMXPlugin)
+ destroyOMXPlugin(*it);
+ else
+ delete *it;
*it = NULL;
}
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index ce10812..dc6f2c9 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -71,8 +71,8 @@
mANW.clear();
}
- const int mYuvTexWidth;// = 64;
- const int mYuvTexHeight;// = 66;
+ const int mYuvTexWidth;
+ const int mYuvTexHeight;
sp<SurfaceMediaSource> mSMS;
sp<SurfaceTextureClient> mSTC;
@@ -124,7 +124,6 @@
// TODO: overwriting the colorformat since the format set by GRAlloc
// could be wrong or not be read by OMX
enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- // colorFormat);
sp<MediaSource> encoder =
@@ -225,7 +224,6 @@
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -239,7 +237,6 @@
// setting the client side buffer size different than the server size
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
10, 10, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -258,6 +255,7 @@
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
@@ -276,10 +274,12 @@
// A dummy writer is used to simulate actual MPEG4Writer
TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
@@ -322,10 +322,9 @@
TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
LOGV("Testing the whole pipeline with actual Recorder");
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- 0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // ));
+ 0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
-
OMXClient client;
CHECK_EQ(OK, client.connect());
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index fd73430..51a631f 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -88,6 +88,12 @@
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
+ // notifyPixelsChanged() needs be called to apply writes to GL-backed
+ // bitmaps. Note that this will slow down read-only accesses to the
+ // bitmaps, but the NDK methods are primarily intended to be used for
+ // writes.
+ bm->notifyPixelsChanged();
+
bm->unlockPixels();
return ANDROID_BITMAP_RESUT_SUCCESS;
}
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 0d8ea28..7a0dcd3 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -415,8 +415,7 @@
AMOTION_EVENT_TOOL_TYPE_FINGER = 1,
AMOTION_EVENT_TOOL_TYPE_STYLUS = 2,
AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER = 4,
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS = 5,
+ AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
};
/*
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index a4564e6..08dcfae 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -29,11 +29,25 @@
android:layout_marginBottom="30dp"
android:text="@string/backup_confirm_text" />
+ <TextView android:id="@+id/password_desc"
+ android:layout_below="@id/confirm_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:text="@string/backup_password_text" />
+
+ <EditText android:id="@+id/password"
+ android:layout_below="@id/password_desc"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="30dp"
+ android:password="true" />
+
<TextView android:id="@+id/package_name"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginLeft="30dp"
- android:layout_below="@id/confirm_text"
+ android:layout_below="@id/password"
android:layout_marginBottom="30dp" />
<Button android:id="@+id/button_allow"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index ca99ae1..8b12ed4 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -29,11 +29,25 @@
android:layout_marginBottom="30dp"
android:text="@string/restore_confirm_text" />
+ <TextView android:id="@+id/password_desc"
+ android:layout_below="@id/confirm_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:text="@string/restore_password_text" />
+
+ <EditText android:id="@+id/password"
+ android:layout_below="@id/password_desc"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="30dp"
+ android:password="true" />
+
<TextView android:id="@+id/package_name"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginLeft="30dp"
- android:layout_below="@id/confirm_text"
+ android:layout_below="@id/password"
android:layout_marginBottom="30dp" />
<Button android:id="@+id/button_allow"
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index 3d85e86..48a8df6 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -29,4 +29,11 @@
<!-- Button to refuse to allow the requested full restore -->
<string name="deny_restore_button_label">Do not restore</string>
+ <!-- Text for message to user that they must enter their predefined backup password in order to perform this operation. -->
+ <string name="backup_password_text">Please enter your predefined backup password below. The full backup will also be encrypted using this password:</string>
+ <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
+ <string name="backup_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
+
+ <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
+ <string name="restore_password_text">If the backup data is encrypted, please enter the password below:</string>
</resources>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index ed413e6..fad58b9 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -126,7 +126,7 @@
final Intent intent = getIntent();
final String action = intent.getAction();
- int layoutId;
+ final int layoutId;
if (action.equals(FullBackup.FULL_BACKUP_INTENT_ACTION)) {
layoutId = R.layout.confirm_backup;
} else if (action.equals(FullBackup.FULL_RESTORE_INTENT_ACTION)) {
@@ -156,6 +156,20 @@
mAllowButton = (Button) findViewById(R.id.button_allow);
mDenyButton = (Button) findViewById(R.id.button_deny);
+ // For full backup, we vary the password prompt text depending on whether one is predefined
+ if (layoutId == R.layout.confirm_backup) {
+ TextView pwDesc = (TextView) findViewById(R.id.password_desc);
+ try {
+ if (mBackupManager.hasBackupPassword()) {
+ pwDesc.setText(R.string.backup_password_text);
+ } else {
+ pwDesc.setText(R.string.backup_password_optional);
+ }
+ } catch (RemoteException e) {
+ // TODO: bail gracefully
+ }
+ }
+
mAllowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -188,8 +202,11 @@
void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
if (!mDidAcknowledge) {
mDidAcknowledge = true;
+
try {
- mBackupManager.acknowledgeFullBackupOrRestore(mToken, true, mObserver);
+ TextView pwView = (TextView) findViewById(R.id.password);
+ mBackupManager.acknowledgeFullBackupOrRestore(mToken, allow,
+ String.valueOf(pwView.getText()), mObserver);
} catch (RemoteException e) {
// TODO: bail gracefully if we can't contact the backup manager
}
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index b0597c4e..0f47482 100755
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -9,7 +9,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
- <application android:label="@string/service_name">
+ <application android:label="@string/service_name"
+ android:allowBackup="false">
<service android:name=".DefaultContainerService"
android:enabled="true"
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 15c1653..626cc86 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -515,34 +515,7 @@
// Check all the native files that need to be copied and add that to the
// container size.
- ZipFile zipFile;
- final List<Pair<ZipEntry, String>> nativeFiles;
- try {
- zipFile = new ZipFile(apkFile);
-
- if (outFiles != null) {
- nativeFiles = outFiles;
- } else {
- nativeFiles = new ArrayList<Pair<ZipEntry, String>>();
- }
-
- NativeLibraryHelper.listPackageNativeBinariesLI(zipFile, nativeFiles);
-
- final int N = nativeFiles.size();
- for (int i = 0; i < N; i++) {
- final Pair<ZipEntry, String> entry = nativeFiles.get(i);
-
- /*
- * Note a 1MB padding is added to the claimed size, so we don't
- * have to worry about block alignment here.
- */
- sizeBytes += entry.first.getSize();
- }
- } catch (ZipException e) {
- Log.w(TAG, "Failed to extract data from package file", e);
- } catch (IOException e) {
- Log.w(TAG, "Failed to cache package shared libs", e);
- }
+ sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
int sizeMb = (int) (sizeBytes >> 20);
if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) {
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index 61f3d11..cb5a781 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4567566098528588863">" Izilungiselelo zokugcina"</string>
+ <string name="app_label" msgid="4567566098528588863">"Izilungiselelo zesitoreji"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index b349030..c61da4e 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -112,6 +112,9 @@
0x200000038=0x03000701:0x03010701:0x03020701;
</string>
+ <!-- Default for Settings.Secure.TOUCH_EXPLORATION_ENABLED -->
+ <bool name="def_touch_exploration_enabled">false</bool>
+
<!-- Default for Settings.System.USER_ROTATION -->
<integer name="def_user_rotation">0</integer>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index a5022e9..7fecc9c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -63,7 +63,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 67;
+ private static final int DATABASE_VERSION = 68;
private Context mContext;
@@ -891,6 +891,25 @@
upgradeVersion = 67;
}
+ if (upgradeVersion == 67) {
+ // New setting to enable touch exploration.
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
+ R.bool.def_touch_exploration_enabled);
+ stmt.close();
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 68;
+ }
+
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1427,6 +1446,9 @@
loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
R.integer.def_long_press_timeout_millis);
+
+ loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
+ R.bool.def_touch_exploration_enabled);
} finally {
if (stmt != null) stmt.close();
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 3a7a6e1..4f39e69 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -201,16 +201,22 @@
BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
DataOutputStream out = new DataOutputStream(bufstream);
+ if (DEBUG_BACKUP) Log.d(TAG, "Writing flattened data version " + FULL_BACKUP_VERSION);
out.writeInt(FULL_BACKUP_VERSION);
+ if (DEBUG_BACKUP) Log.d(TAG, systemSettingsData.length + " bytes of settings data");
out.writeInt(systemSettingsData.length);
out.write(systemSettingsData);
+ if (DEBUG_BACKUP) Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
out.writeInt(secureSettingsData.length);
out.write(secureSettingsData);
+ if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data");
out.writeInt(locale.length);
out.write(locale);
+ if (DEBUG_BACKUP) Log.d(TAG, wifiSupplicantData.length + " bytes of wifi supplicant data");
out.writeInt(wifiSupplicantData.length);
out.write(wifiSupplicantData);
+ if (DEBUG_BACKUP) Log.d(TAG, wifiConfigData.length + " bytes of wifi config data");
out.writeInt(wifiConfigData.length);
out.write(wifiConfigData);
@@ -241,28 +247,28 @@
int nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data");
byte[] buffer = new byte[nBytes];
- in.read(buffer, 0, nBytes);
+ in.readFully(buffer, 0, nBytes);
restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI);
// secure settings
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
- in.read(buffer, 0, nBytes);
+ in.readFully(buffer, 0, nBytes);
restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI);
// locale
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of locale data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
- in.read(buffer, 0, nBytes);
+ in.readFully(buffer, 0, nBytes);
mSettingsHelper.setLocaleData(buffer, nBytes);
// wifi supplicant
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi supplicant data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
- in.read(buffer, 0, nBytes);
+ in.readFully(buffer, 0, nBytes);
int retainedWifiState = enableWifi(false);
restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, buffer, nBytes);
FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
@@ -277,7 +283,7 @@
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi config data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
- in.read(buffer, 0, nBytes);
+ in.readFully(buffer, 0, nBytes);
restoreFileData(mWifiConfigFile, buffer, nBytes);
if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d32df6e..cf0bdd3 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -13,6 +13,7 @@
<application
android:persistent="true"
android:allowClearUserData="false"
+ android:allowBackup="false"
android:hardwareAccelerated="true"
android:label="@string/app_label"
android:icon="@drawable/ic_launcher_settings">
@@ -82,5 +83,17 @@
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
+
+ <!-- started from NetworkPolicyManagerService -->
+ <activity
+ android:name=".net.NetworkOverLimitActivity"
+ android:exported="true"
+ android:permission="android.permission.MANAGE_NETWORK_POLICY"
+ android:theme="@android:style/Theme.Holo.Panel"
+ android:finishOnCloseSystemDialogs="true"
+ android:launchMode="singleTop"
+ android:taskAffinity="com.android.systemui.net"
+ android:excludeFromRecents="true" />
+
</application>
</manifest>
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 48f6122..2aeb84a 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_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index 1439ece..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 06c3369..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a1a712f..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 313f0f5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 75def49..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index efbd535..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e0dca0b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 54ee2e6..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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 686158b..2aeb84a 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_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
deleted file mode 100644
index 76170a8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 97d35f3..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 17423d2..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index ae58b57..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 00e5bb8..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b036a89..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index bdae6fb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 2b7d95f..0000000
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
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 6e5f131..35d0a06 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-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_0_fully.png
index 0cfdca0..d52cb1a 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_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index 7bbfbd1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 60b75ef..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 0fba69d..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index da8a957..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e19bf64..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 8387514..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 35f7741..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a8820e9..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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 b65df27..d52cb1a 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_wifi_signal_1_flowing.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
deleted file mode 100644
index 0478d70..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index e78a0b1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 24c75ec..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 7027dc4..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b0e83dc..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 01945ff..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 725a507..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 193af25..0000000
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
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
index 22215ab..79da092 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.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
index ec4f934..726f7ad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_0_fully.png
+++ 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_flowing.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
deleted file mode 100644
index fb98eef..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index b86d47a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 7269f96..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index f57e62d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 3d513fb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 32556f9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index afac648..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 60c0e7f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4_fully_flowing.png
+++ /dev/null
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
index 0df470a..726f7ad 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_null.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
deleted file mode 100644
index d8d5e8f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 2b0b54f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 85c65b4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_flowing.png
+++ /dev/null
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
deleted file mode 100644
index a7e9aaf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 21aba7e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 41db8dc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3_fully_flowing.png
+++ /dev/null
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
deleted file mode 100644
index ae95d26..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_flowing.png
+++ /dev/null
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
deleted file mode 100644
index 4ad2c5c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4_fully_flowing.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..8a9deea
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-hdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..2de4515
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_0_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png
new file mode 100644
index 0000000..b9410f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xlarge-xhdpi/stat_sys_signal_null.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/stat_sys_battery.xml b/packages/SystemUI/res/drawable/stat_sys_battery.xml
new file mode 100644
index 0000000..744ab93
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_battery.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_0" />
+ <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_15" />
+ <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_28" />
+ <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_43" />
+ <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_57" />
+ <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_71" />
+ <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_85" />
+ <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_100" />
+</level-list>
+
diff --git a/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml
new file mode 100644
index 0000000..6918eb2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<level-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_charge_anim0" />
+ <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_charge_anim15" />
+ <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_charge_anim28" />
+ <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_charge_anim43" />
+ <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_charge_anim57" />
+ <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_charge_anim71" />
+ <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_charge_anim85" />
+ <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_charge_anim100" />
+</level-list>
+
+
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
index 1e3099d..17fa653 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_area.xml
@@ -126,27 +126,10 @@
android:layout_width="wrap_content"
android:visibility="gone"
/>
- <FrameLayout
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_marginRight="4dp"
- >
- <ImageView
- android:id="@+id/network_signal"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
- <ImageView
- android:id="@+id/network_type"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
- <ImageView
- android:id="@+id/network_direction"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
- </FrameLayout>
+ <include layout="@layout/stacked_signal_icons"
+ android:layout_width="32dp"
+ android:layout_height="24dp"
+ />
<ImageView
android:id="@+id/battery"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/stacked_signal_icons.xml b/packages/SystemUI/res/layout/stacked_signal_icons.xml
new file mode 100644
index 0000000..fdeb74b
--- /dev/null
+++ b/packages/SystemUI/res/layout/stacked_signal_icons.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** 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.
+*/
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ >
+ <ImageView
+ android:id="@+id/mobile_signal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignLeft="@+id/wifi_signal"
+ android:layout_alignWithParentIfMissing="true"
+ />
+ <ImageView
+ android:id="@+id/network_type"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_alignRight="@id/mobile_signal"
+ android:layout_centerVertical="true"
+ />
+ <ImageView
+ android:id="@+id/wifi_signal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:scaleType="center"
+ android:paddingLeft="7dp"
+ />
+ <ImageView
+ android:id="@+id/network_direction"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index c8f5772..0f5aa93 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -46,10 +46,29 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
- android:paddingRight="6dip"
android:gravity="center_vertical"
android:orientation="horizontal"/>
+ <LinearLayout
+ android:id="@+id/signal_battery_cluster"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginRight="6dp"
+ android:orientation="horizontal"
+ android:gravity="center"
+ >
+ <include layout="@layout/stacked_signal_icons"
+ android:layout_width="24dp"
+ android:layout_height="match_parent"
+ />
+ <ImageView
+ android:id="@+id/battery"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingLeft="6dip"
+ />
+ </LinearLayout>
+
<com.android.systemui.statusbar.policy.Clock
android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index bf18e3b..116d6a0 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Maak skoon"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
<skip />
<!-- no translation found for screenshot_failed_toast (655180965533683356) -->
<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 />
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7e15fe0..740fb2a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
<skip />
<!-- no translation found for screenshot_failed_toast (655180965533683356) -->
<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 />
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f22a657..5b1d492 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"محو"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ليس هناك أي تنبيهات"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"مستمر"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"التنبيهات"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"عند تصميم تطبيق لشاشة أصغر، سيظهر عنصر تحكم في التكبير/التصغير بجوار الساعة."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"تم حفظ لقطة الشاشة إلى المعرض."</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"تعذر حفظ لقطة الشاشة."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"خيارات نقل الملفات عبر USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"تحميل كمشغل وسائط (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"تحميل ككاميرا (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"تثبيت تطبيق Android File Transfer لـ Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 7560aca..4890c0d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Изчистване"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Няма известия"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"В момента"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Когато дадено приложение е създадено за по-малък екран, до часовника ще се покаже управление за промяна на мащаба."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Екранната снимка е запазена в галерията"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Екранната снимка не можа да бъде запазена"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Свързване като камера (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Инсталиране на Android File Transfer за Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index cba8db4..417987c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Esborra"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molesteu"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostra notificacions"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Cap notificació"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Quan una aplicació s\'hagi dissenyat per a una pantalla més petita, apareixerà un control de zoom al costat del rellotge."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla desada a la galeria"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"No es pot desar la captura de pantalla"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instal·la aplic. transf. fitxers Android per a Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index acdbbe5..7544876 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazat"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nerušit"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Zobrazit upozornění"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žádná oznámení"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Pokud je aplikace navržena pro menší obrazovku, zobrazí se vedle hodin ovládací prvek přiblížení."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímek obrazovky byl uložen do Galerie"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Snímek obrazovky se nepodařilo uložit"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Připojit jako fotoaparát (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalovat aplikaci Android File Transfer pro Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d74dc62..89c6b64 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ryd"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Forstyr ikke"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Vis meddelelser"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelelser"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er udviklet til en mindre skærm, vises der en zoomfunktion ved uret."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Skærmbilledet gemmes i Galleri"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Skærmbilledet kunne ikke gemmes"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Isæt som et kamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer appen Android File Transfer Manager til Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e09598f..dc68c22 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Löschen"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Bitte nicht stören"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Benachrichtigungen zeigen"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
@@ -57,6 +61,104 @@
<string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
<string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitätszoom"</string>
<string name="compat_mode_help_body" msgid="4946726776359270040">"Wenn eine App für einen kleineren Bildschirm ausgelegt ist, wird ein Zoom-Steuerelement neben der Uhr angezeigt."</string>
- <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot in Galerie gespeichert."</string>
+ <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot in Galerie gespeichert"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Screenshot konnte nicht gespeichert werden."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"App \"Android File Transfer\" für Mac installieren"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1fc6871..29d84cb 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Δεν υπάρχουν ειδοποιήσεις"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Όταν μια εφαρμογή έχει σχεδιαστεί για προβολή σε μικρότερη οθόνη, δίπλα από το ρολόι θα εμφανιστεί ένα στοιχείο ελέγχου ζουμ."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Το στιγμιότυπο οθόνης αποθηκεύτηκε στη συλλογή"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Δεν ήταν δυνατή η αποθήκευση του στιγμιοτύπου οθόνης"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Προσάρτηση ως κάμερας (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Εγκατάσταση της εφαρμογής μεταφοράς αρχείων Android για Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c9bb124..2d8c737 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Clear"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Do not disturb"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Show notifications"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -59,4 +63,102 @@
<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>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot saved to Gallery"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Could not save screenshot"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Install Android File Transfer application for Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ace34d6..7ce69b6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Cuando una aplicación fue diseñada para una pantalla más pequeña, aparece un control de zoom junto al reloj."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la Galería"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"No se pudo guardar la captura de pantalla."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar la aplicación para transferir archivos de Android para Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d4594df..1ee4fed 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molestar"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificaciones"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Si la aplicación se ha diseñado para una pantalla más pequeña, aparecerá un control de zoom junto al reloj."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la galería"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"No se ha podido guardar la captura de pantalla."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar la aplicación para transferir archivos de Android para Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 81d3b84..dbdcbb6 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"پاک کردن"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"اعلانی موجود نیست"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان ها"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"اگر یک برنامه برای صفحه کوچک تری طراحی شده باشد، یک کنترل بزرگنمایی توسط ساعت نشان داده می شود."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"تصویر از صفحه در گالری ذخیره شد"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"ذخیره تصویر صفحه ممکن نیست"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"گزینه های انتقال فایل USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"نصب به عنوان دستگاه پخش رسانه (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"تصب به عنوان دوربین (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"نصب برنامه انتقال فایل Android برای Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index e0e65ad..bef79a5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Tyhjennä"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Varattu"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Näytä ilmoitukset"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ei ilmoituksia"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Jos sovellus on suunniteltu pienemmälle näytölle, kellon viereen tulee näkyviin zoomaussäädin."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Kuvakaappaus on tallennettu galleriaan"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Kuvakaappausta ei voitu tallentaa"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Asenna Android File Transfer -sovellus Macille"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1342d8b..9815664 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne pas déranger"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Afficher les notifications"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Si une application a été conçue pour un écran plus petit, une commande de zoom s\'affiche à côté de l\'horloge."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Capture d\'écran enregistrée dans la galerie."</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Impossible d\'enregistrer la capture d\'écran."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer en tant qu\'appareil photo (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer application Android File Transfer pour Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index afb18ab..45d2edc 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Očisti"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne uznemiravaj"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Prikaži obavijesti"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bez obavijesti"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Kada je aplikacija dizajnirana za manji zaslon, kontrole zumiranja prikazuju se pored sata."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Snimak zaslona spremljen u Galeriju"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Ne mogu spremiti snimak zaslona"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Učitaj kao fotoaparat (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalacija aplikacije Android File Transfer za Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 448c3e6..468b875 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Törlés"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne zavarjanak"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Értesítések megjelenítése"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nincs értesítés"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Ha egy alkalmazást kisebb képernyőre terveztek, akkor a nagyítás/kicsinyítés vezérlője az óra mellett jelenik meg."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Képernyőkép mentve a galériába"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Nem sikerült menteni a képernyőképet"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Csatlakoztatás kameraként (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Android fájlátviteli alkalmazás telepítése Machez"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 02f1ff6..9da6e73 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Bersihkan"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Jangan ganggu"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Tampilkan pemberitahuan"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tidak ada pemberitahuan"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Saat apl dirancang untuk layar yang lebih kecil, kontrol zoom akan tampil di dekat jam."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan layar disimpan ke Galeri"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak dapat menyimpan tangkapan layar"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer berkas USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Pasang aplikasi Transfer Berkas Android untuk Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 763842a..476f190 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Cancella"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Non disturbare"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostra notifiche"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Se un\'applicazione è stata progettata per uno schermo più piccolo, accanto all\'orologio viene visualizzato un controllo dello zoom."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot salvato nella galleria"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Impossibile salvare lo screenshot"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Monta come videocamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Installa l\'applicazione Android File Transfer per Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 5236740..4552f23 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"נקה"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"אין התראות"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתבצע"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"התראות"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"כאשר יישום מיועד למסך קטן יותר, פקד של מרחק מתצוגה יופיע ליד השעון."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"צילום המסך נשמר בגלריה"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"לא ניתן לשמור את צילום המסך"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"אפשרויות העברת קבצים ב-USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"טען כנגן מדיה (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"טען כמצלמה (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"התקן את יישום העברת הקבצים של Android עבור Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2e0fad2..abee692 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"通知を消去"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"通知なし"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"より小型の画面向けのアプリの場合は、ズームコントロールが時計のそばに表示されます。"</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"スクリーンショットがギャラリーに保存されました"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"スクリーンショットを保存できませんでした"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"カメラ(PTP)としてマウント"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac版Android File Transferアプリのインストール"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a46b608..c34f0e4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"지우기"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"알림 없음"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"앱이 작은 화면에 맞도록 설계된 경우 시계 옆에 확대/축소 컨트롤이 표시됩니다."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"캡쳐화면이 갤러리에 저장되었습니다."</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"캡쳐화면을 저장하지 못했습니다."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"카메라로 마운트(PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac용 Android 파일 전송 애플리케이션 설치"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-large/strings.xml b/packages/SystemUI/res/values-large/strings.xml
index 35be532..f04dc04 100644
--- a/packages/SystemUI/res/values-large/strings.xml
+++ b/packages/SystemUI/res/values-large/strings.xml
@@ -21,29 +21,9 @@
all of the currently visible notifications. [CHAR LIMIT=10]-->
<string name="status_bar_clear_all_button">Clear all</string>
- <!-- System panel ("Quick Settings") -->
-
- <!-- Text to display underneath the graphical signal strength meter when
- no connection is available. [CHAR LIMIT=20] -->
- <string name="status_bar_settings_signal_meter_disconnected">
- No Internet connection
- </string>
-
- <!-- Text to display underneath the graphical signal strength meter when
- it is displaying Wi-Fi status and Wi-Fi is connected to a network
- whose SSID is not available.
- [CHAR LIMIT=20] -->
- <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string>
-
<!-- Separator for PLMN and SPN in network name. -->
<string name="status_bar_network_name_separator" translatable="false">" – "</string>
- <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] -->
- <string name="gps_notification_searching_text">Searching for GPS</string>
-
- <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
- <string name="gps_notification_found_text">Location set by GPS</string>
-
<!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
mode) -->
<string name="notifications_off_title">Notifications off</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 356f46b..040c74d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Išvalyti"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netrukdyti"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rodyti pranešimus"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nėra įspėjimų"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Įspėjimai"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Kai programa bus pritaikyta mažesniam ekranui, mastelio keitimo valdiklis bus parodytas šalia laikrodžio."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrano kopija išsaugota galerijoje"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Nepavyko išsaugoti ekrano kopijos"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos grotuvą (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Įdiegti „Mac“ skirtą „Android“ failų perd. progr."</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bf6dbd4..4c9b4b4 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Notīrīt"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netraucēt"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rādīt paziņojumus"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nav paziņojumu"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Ja lietotne ir paredzēta mazākam ekrānam, blakus pulkstenim tiks parādīta tālummaiņas vadīkla."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekrānuzņēmums ir saglabāts galerijā."</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Nevarēja saglabāt ekrānuzņēmumu."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Pievienot kā kameru (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalēt Android failu pārsūt. liet. Mac datoram"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms-large/strings.xml b/packages/SystemUI/res/values-ms-large/strings.xml
new file mode 100644
index 0000000..4897656
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-large/strings.xml
@@ -0,0 +1,29 @@
+<?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="status_bar_clear_all_button" msgid="4661583896803349732">"Ksgkn smua"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Tiada smbg Internet"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Wi-Fi disambungkan"</string>
+ <string name="gps_notification_searching_text" msgid="4467935186864208249">"Mencari GPS"</string>
+ <string name="gps_notification_found_text" msgid="6270628388918822956">"Lokasi ditetapkan oleh GPS"</string>
+ <string name="notifications_off_title" msgid="1860117696034775851">"Pemberitahuan dimatikan"</string>
+ <string name="notifications_off_text" msgid="1439152806320786912">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index d51f0cc..eef7926 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -23,6 +23,10 @@
<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>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<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>
@@ -53,14 +57,108 @@
<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 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 />
+ <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
+ <string name="compat_mode_help_header" msgid="7020175705401506719">"Keserasian Zum"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"Apabila apl direka untuk skrin yang lebih kecil, kawalan zum akan muncul di tepi jam."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Tangkapan skrin disimpan ke Galeri"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Tidak boleh menyimpan tangkapan skrin"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Lekapkan sebagai kamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Pasang aplikasi Pemindahan Fail Android untuk Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index be10217..589a6ab 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Fjern"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ikke forstyrr"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Vis varslinger"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varslinger"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Når en app er utformet for en mindre skjerm, vises det en zoomkontroll ved klokken."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Skjermdump ble lagret i galleriet"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Lagring av skjermdump mislyktes"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Sett inn som kamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Installer Android File Transfer for Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c83c7c4..ab44aaf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wissen"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Niet storen"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Meldingen weergeven"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Wanneer een app is ontworpen voor een kleiner scherm, wordt naast de klok een zoomknop weergegeven."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Schermafbeelding is opgeslagen in de galerij"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Schermafbeelding is niet opgeslagen"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Koppelen als camera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Applicatie Android File Transfer voor Mac installeren"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e5937e2..977ba60 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wyczyść"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nie przeszkadzać"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Pokaż powiadomienia"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Jeśli aplikacja została przystosowana do mniejszego ekranu, obok zegara zostanie wyświetlony element sterujący powiększeniem."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Zrzut ekranu został zapisany w galerii."</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Nie można zapisać zrzutu ekranu."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Podłącz jako aparat (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Zainstaluj aplikację Android File Transfer dla Mac OS"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 400d805..2c6d283 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Não incomodar"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificações"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Sempre que uma aplicação tiver sido concebida para ecrãs mais pequenos, aparecerá um controlo de zoom junto ao relógio."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecrã guardada na Galeria"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível guardar a captura de ecrã"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar a ap. Trans. de Fic. do Android para Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 90dd212..29aa510 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Não perturbe"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostrar notificações"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Quando um aplicativo é desenvolvido para uma tela menor, um controle de zoom é exibido perto do relógio."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"A captura de tela foi salva na Galeria"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Não foi possível salvar a captura de tela"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalar aplic. Android File Transfer para Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 2f23275..b2c8b50 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -26,6 +26,10 @@
<skip />
<!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
<skip />
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nagins avis"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actual"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Avis"</string>
@@ -91,4 +95,106 @@
<skip />
<!-- no translation found for screenshot_failed_toast (655180965533683356) -->
<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 />
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 6dfd055..5128088 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ştergeţi"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nu deranjaţi"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Afişaţi notificări"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nicio notificare"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfăşurare"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Atunci când o aplicaţie a fost concepută pentru un ecran mai mic, o comandă pentru mărire/micşorare va apărea alături de ceas."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecran a fost salvată în Galerie"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Captura de ecran nu a putut fi salvată"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opţiuni pentru transferul de fişiere prin USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Montaţi ca player media (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Montaţi drept cameră foto (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Instalaţi aplicaţia Transfer de fişiere Android pentru Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d1f6cd2..2f22ab4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нет уведомлений"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Если приложение рассчитано на экран меньших размеров, рядом с часами появятся средства масштабирования."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Скриншот сохранен в галерее"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Не удалось сохранить скриншот"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Установить Android File Transfer для Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d67752b..9701572 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazať"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nerušiť"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Zobraziť upozornenia"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žiadne upozornenia"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Ak je aplikácia navrhnutá pre menšiu obrazovku, zobrazí sa vedľa hodín ovládací prvok priblíženia."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Snímka obrazovky bola uložená do Galérie"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Snímku obrazovky sa nepodarilo uložiť"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Pripojiť ako fotoaparát (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Inštalovať aplikáciu Prenos súborov Android pre systém Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c7aade9..2b89f88 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Počisti"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne moti"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Pokaži obvestila"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ni obvestil"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Če je program izdelan za manjše zaslone, se ob uri pokaže kontrolnik za povečavo."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Posnetek zaslona je shranjen v galerijo"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Posnetka zaslona ni bilo mogoče shraniti"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Vpni kot fotoaparat (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Namestite program Android File Transfer za Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0afdf98..fcd612f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Обриши"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нема обавештења"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текуће"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Када је апликација намењена мањем екрану, контрола зумирања приказује се поред сата."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Снимак екрана је сачуван у Галерији"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Није могуће сачувати снимак екрана"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Прикључи као камеру (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Инсталирај апликацију Android File Transfer за Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6cbca3f..6f3b2bb 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ta bort"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Stör ej"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Visa aviseringar"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"När en app är anpassad för en mindre skärm visas ett zoomreglage vid klockan."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Skärmdumpen sparades i galleriet"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Det gick inte att spara skärmdumpen"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Montera som kamera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Installera Android-filöverföringsapp för Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 17ec8a1..450157c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Futa"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
<skip />
<!-- no translation found for screenshot_failed_toast (655180965533683356) -->
<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 />
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index b4fd8ab..a5bea5c 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -64,4 +64,10 @@
<!-- Where to place the app icon over the thumbnail -->
<dimen name="status_bar_recents_app_icon_left_margin">13dp</dimen>
<dimen name="status_bar_recents_app_icon_top_margin">13dp</dimen>
+
+ <!-- size at which Notification icons will be drawn in the status bar -->
+ <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+
+ <!-- opacity at which Notification icons will be drawn in the status bar -->
+ <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..6736c1a
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -0,0 +1,25 @@
+<?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.
+*/
+-->
+<resources>
+ <!-- size at which Notification icons will be drawn in the status bar -->
+ <dimen name="status_bar_icon_drawing_size">24dip</dimen>
+
+ <!-- opacity at which Notification icons will be drawn in the status bar -->
+ <item type="dimen" name="status_bar_icon_drawing_alpha">100%</item>
+</resources>
+
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 9744c60..a5315c6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"ล้างข้อมูล"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ไม่มีการแจ้งเตือน"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ดำเนินอยู่"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"สำหรับแอปพลิเคชันที่ออกแบบมาสำหรับหน้าจอขนาดเล็ก ตัวควบคุมการย่อ/ขยายจะปรากฏขึ้นข้างนาฬิกา"</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"บันทึกภาพหน้าจอในแกลเลอรีแล้ว"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"ไม่สามารถบันทึกภาพหน้าจอ"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"ติดตั้งแอปพลิเคชัน Android File Transfer ของ Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 93796f3..d44f82e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"I-clear"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Huwag gambalain"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Magpakita ng notification"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Walang mga notification"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Kapag nakadisenyo ang isang app para sa mas maliit na screen, isang kontrol ng zoom ang lalabas sa may orasan."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Na-save ang screenshot sa Gallery"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Hindi ma-save ang screenshot"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"I-mount bilang camera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"I-install Android File Transfer para sa Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2fd0df5..308c434 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Temizle"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Rahatsız etmeyin"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Bildirimleri göster"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildirim yok"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Uygulama küçük bir ekran için tasarlanmışsa saatin yanında bir yakınlaştırma denetimi görünür."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Ekran görüntüsü Galeri\'ye kaydedildi"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Ekran görüntüsü kaydedilemedi"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera olarak ekle (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Mac için Android Dosya Aktarımı uygulamasını yükle"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a81dbbf..6687d0c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очист."</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Немає сповіщень"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Якщо програму призначено для менших екранів, елемент керування масштабом буде відображатися біля годинника."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Знімок екрана збережено в Галереї"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Неможливо зберегти знімок екрана"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Підключити як камеру (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Установити програму Android File Transfer для Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index b660b98..5bca34b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xoá"</string>
<string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Không làm phiền"</string>
<string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Hiển thị thông báo"</string>
+ <!-- no translation found for status_bar_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Không có thông báo nào"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"Khi ứng dụng được thiết kế cho một màn hình nhỏ hơn, điều khiển thu phóng sẽ xuất hiện bên cạnh đồng hồ."</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"Đã lưu ảnh chụp màn hình vào Thư viện"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"Không thể lưu ảnh chụp màn hình"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Gắn như một máy ảnh (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"Cài đặt ứng dụng Truyền tệp của Android dành cho Mac"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 397d590..dfab6d7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"如果应用程序是针对较小屏幕设计的,则时钟旁会显示缩放控件。"</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"屏幕截图已保存到“图库”"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"无法保存屏幕截图"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB 文件传输选项"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器 (MTP) 装载"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"作为摄像头 (PTP) 装载"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"安装适用于苹果机的“Android 文件传输”应用程序"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 61afd2ff..854d89d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"沒有通知"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
@@ -59,4 +63,102 @@
<string name="compat_mode_help_body" msgid="4946726776359270040">"執行專為較小螢幕設計的應用程式時,系統會在時鐘旁顯示縮放控制項。"</string>
<string name="screenshot_saving_toast" msgid="8592630119048713208">"螢幕擷取畫面已儲存至圖片庫"</string>
<string name="screenshot_failed_toast" msgid="655180965533683356">"無法儲存螢幕擷取畫面"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="8485631662288445893">"安裝適用於 Mac 的「Android 檔案傳輸」"</string>
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 01db97f..05268bf 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -23,6 +23,10 @@
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"Sula"</string>
<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_recent_remove_item_title (6561944127804037619) -->
+ <skip />
+ <!-- no translation found for status_bar_recent_inspect_item_title (4906947311448880529) -->
+ <skip />
<!-- no translation found for status_bar_no_notifications_title (4755261167193833213) -->
<skip />
<!-- no translation found for status_bar_ongoing_events_title (1682504513316879202) -->
@@ -81,4 +85,106 @@
<skip />
<!-- no translation found for screenshot_failed_toast (655180965533683356) -->
<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 />
+ <!-- no translation found for accessibility_back (567011538994429120) -->
+ <skip />
+ <!-- no translation found for accessibility_home (8217216074895377641) -->
+ <skip />
+ <!-- no translation found for accessibility_menu (316839303324695949) -->
+ <skip />
+ <!-- no translation found for accessibility_ime_switch_button (5032926134740456424) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_button (8461115318742350699) -->
+ <skip />
+ <!-- no translation found for accessibility_compatibility_zoom_example (4220687294564945780) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_connected (2707027633242983370) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_disconnected (7416648669976870175) -->
+ <skip />
+ <!-- no translation found for accessibility_no_battery (358343022352820946) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_one_bar (7774887721891057523) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_two_bars (8500650438735009973) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_three_bars (2302983330865040446) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_full (8909122401720158582) -->
+ <skip />
+ <!-- no translation found for accessibility_no_phone (4894708937052611281) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_one_bar (687699278132664115) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_two_bars (8384905382804815201) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_three_bars (8521904843919971885) -->
+ <skip />
+ <!-- no translation found for accessibility_phone_signal_full (6471834868580757898) -->
+ <skip />
+ <!-- no translation found for accessibility_no_data (4791966295096867555) -->
+ <skip />
+ <!-- no translation found for accessibility_data_one_bar (1415625833238273628) -->
+ <skip />
+ <!-- no translation found for accessibility_data_two_bars (6166018492360432091) -->
+ <skip />
+ <!-- no translation found for accessibility_data_three_bars (9167670452395038520) -->
+ <skip />
+ <!-- no translation found for accessibility_data_signal_full (2708384608124519369) -->
+ <skip />
+ <!-- no translation found for accessibility_no_wifi (4017628918351949575) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_one_bar (1914343229091303434) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_two_bars (7869150535859760698) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_three_bars (2665319332961356254) -->
+ <skip />
+ <!-- no translation found for accessibility_wifi_signal_full (1275764416228473932) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3g (8628562305003568260) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_3.5g (8664845609981692001) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_4g (7741000750630089612) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_cdma (6132648193978823023) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_edge (4477457051631979278) -->
+ <skip />
+ <!-- no translation found for accessibility_data_connection_wifi (1127208787254436420) -->
+ <skip />
+ <!-- no translation found for accessibility_no_sim (8274017118472455155) -->
+ <skip />
+ <!-- no translation found for accessibility_bluetooth_tether (4102784498140271969) -->
+ <skip />
+ <!-- no translation found for accessibility_airplane_mode (834748999790763092) -->
+ <skip />
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <!-- no translation found for accessibility_settings_button (7913780116850379698) -->
+ <skip />
+ <!-- no translation found for accessibility_notifications_button (2933903195211483438) -->
+ <skip />
+ <!-- no translation found for accessibility_remove_notification (4883990503785778699) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_enabled (3511469499240123019) -->
+ <skip />
+ <!-- no translation found for accessibility_gps_acquiring (8959333351058967158) -->
+ <skip />
+ <!-- no translation found for accessibility_tty_enabled (4613200365379426561) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_vibrate (666585363364155055) -->
+ <skip />
+ <!-- no translation found for accessibility_ringer_silent (9061243307939135383) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index da28e1e..b02015d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -48,5 +48,13 @@
<!-- thickness (height) of each notification row, including any separators or padding -->
<dimen name="notification_height">65dp</dimen>
-</resources>
+ <!-- Height of notification icons in the status bar -->
+ <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
+
+ <!-- size at which Notification icons will be drawn in the status bar -->
+ <dimen name="status_bar_icon_drawing_size">18dip</dimen>
+
+ <!-- opacity at which Notification icons will be drawn in the status bar -->
+ <item type="dimen" name="status_bar_icon_drawing_alpha">40%</item>
+</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 082dab3..5ca77fc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -158,7 +158,7 @@
<!-- Checkbox label for application compatibility mode OFF (normal mode on tablets).
[CHAR LIMIT=25] -->
<string name="compat_mode_off">Stretch to fill screen</string>
-
+
<!-- Compatibility mode help screen: header text. [CHAR LIMIT=50] -->
<string name="compat_mode_help_header">Compatibility Zoom</string>
@@ -168,7 +168,7 @@
<!-- toast message displayed when a screenshot is saved to the Gallery. -->
<string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
<!-- toast message displayed when we fail to take a screenshot. -->
- <string name="screenshot_failed_toast">Could not save screenshot</string>
+ <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
@@ -300,4 +300,35 @@
<!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_ringer_silent">Ringer silent.</string>
+ <!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+ <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
+ <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+ <string name="data_usage_disabled_dialog_4g_title">4G data disabled</string>
+ <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+ <string name="data_usage_disabled_dialog_mobile_title">Mobile data disabled</string>
+ <!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
+ <string name="data_usage_disabled_dialog_title">Data disabled</string>
+ <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
+ <string name="data_usage_disabled_dialog">The specified data usage limit has been reached.\n\nAdditional data use may incur carrier charges.</string>
+ <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
+ <string name="data_usage_disabled_dialog_enable">Re-enable data</string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ no connection is available. [CHAR LIMIT=20] -->
+ <string name="status_bar_settings_signal_meter_disconnected">
+ No Internet connection
+ </string>
+
+ <!-- Text to display underneath the graphical signal strength meter when
+ it is displaying Wi-Fi status and Wi-Fi is connected to a network
+ whose SSID is not available.
+ [CHAR LIMIT=20] -->
+ <string name="status_bar_settings_signal_meter_wifi_nossid">Wi-Fi connected</string>
+
+ <!-- Notification text: when GPS is getting a fix [CHAR LIMIT=50] -->
+ <string name="gps_notification_searching_text">Searching for GPS</string>
+
+ <!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
+ <string name="gps_notification_found_text">Location set by GPS</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
new file mode 100644
index 0000000..eaffd1a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -0,0 +1,317 @@
+/*
+ * 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;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.graphics.RectF;
+import android.util.Log;
+import android.view.animation.LinearInterpolator;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+
+public class SwipeHelper {
+ static final String TAG = "com.android.systemui.SwipeHelper";
+ private static final boolean DEBUG = true;
+ private static final boolean DEBUG_INVALIDATE = false;
+ private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
+
+ public static final int X = 0;
+ public static final int Y = 1;
+
+ private boolean CONSTRAIN_SWIPE = true;
+ private boolean FADE_OUT_DURING_SWIPE = true;
+ private boolean DISMISS_IF_SWIPED_FAR_ENOUGH = true;
+
+ private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
+ private int MAX_ESCAPE_ANIMATION_DURATION = 500; // ms
+ private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 250; // ms
+
+ public static float ALPHA_FADE_START = 0.8f; // fraction of thumbnail width
+ // where fade starts
+ static final float ALPHA_FADE_END = 0.5f; // fraction of thumbnail width
+ // beyond which alpha->0
+
+ private float mPagingTouchSlop;
+ private Callback mCallback;
+ private int mSwipeDirection;
+ private VelocityTracker mVelocityTracker;
+
+ private float mInitialTouchPos;
+ private boolean mDragging;
+ private View mCurrView;
+ private float mDensityScale;
+
+ public SwipeHelper(int swipeDirection, Callback callback, float densityScale,
+ float pagingTouchSlop) {
+ mCallback = callback;
+ mSwipeDirection = swipeDirection;
+ mVelocityTracker = VelocityTracker.obtain();
+ mDensityScale = densityScale;
+ mPagingTouchSlop = pagingTouchSlop;
+ }
+
+ public void setDensityScale(float densityScale) {
+ mDensityScale = densityScale;
+ }
+
+ public void setPagingTouchSlop(float pagingTouchSlop) {
+ mPagingTouchSlop = pagingTouchSlop;
+ }
+
+ private float getPos(MotionEvent ev) {
+ return mSwipeDirection == X ? ev.getX() : ev.getY();
+ }
+
+ private float getPos(View v) {
+ return mSwipeDirection == X ? v.getX() : v.getY();
+ }
+
+ private float getVelocity(VelocityTracker vt) {
+ return mSwipeDirection == X ? vt.getXVelocity() :
+ vt.getYVelocity();
+ }
+
+ private ObjectAnimator createTranslationAnimation(View v, float newPos) {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(v,
+ mSwipeDirection == X ? "translationX" : "translationY", newPos);
+ return anim;
+ }
+
+ private float getPerpendicularVelocity(VelocityTracker vt) {
+ return mSwipeDirection == X ? vt.getYVelocity() :
+ vt.getXVelocity();
+ }
+
+ private void setTranslation(View v, float translate) {
+ if (mSwipeDirection == X) {
+ v.setTranslationX(translate);
+ } else {
+ v.setTranslationY(translate);
+ }
+ }
+
+ private float getSize(View v) {
+ return mSwipeDirection == X ? v.getMeasuredWidth() :
+ v.getMeasuredHeight();
+ }
+
+ private float getContentSize(View v) {
+ View content = mCallback.getChildContentView(v);
+ return getSize(content);
+ }
+
+ private float getAlphaForOffset(View view, float thumbSize) {
+ final float fadeSize = ALPHA_FADE_END * thumbSize;
+ float result = 1.0f;
+ float pos = getPos(view);
+ if (pos >= thumbSize * ALPHA_FADE_START) {
+ result = 1.0f - (pos - thumbSize * ALPHA_FADE_START) / fadeSize;
+ } else if (pos < thumbSize * (1.0f - ALPHA_FADE_START)) {
+ result = 1.0f + (thumbSize * ALPHA_FADE_START + pos) / fadeSize;
+ }
+ return result;
+ }
+
+ void invalidateGlobalRegion(View view) {
+ RectF childBounds = new RectF(view.getLeft(), view.getTop(), view.getRight(), view
+ .getBottom());
+ childBounds.offset(view.getX(), view.getY());
+ if (DEBUG_INVALIDATE)
+ Log.v(TAG, "-------------");
+ while (view.getParent() != null && view.getParent() instanceof View) {
+ view = (View) view.getParent();
+ view.getMatrix().mapRect(childBounds);
+ view.invalidate((int) Math.floor(childBounds.left),
+ (int) Math.floor(childBounds.top),
+ (int) Math.ceil(childBounds.right),
+ (int) Math.ceil(childBounds.bottom));
+ if (DEBUG_INVALIDATE) {
+ Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
+ + "," + (int) Math.floor(childBounds.top)
+ + "," + (int) Math.ceil(childBounds.right)
+ + "," + (int) Math.ceil(childBounds.bottom));
+ }
+ }
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ final int action = ev.getAction();
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mDragging = false;
+ mCurrView = mCallback.getChildAtPosition(ev);
+ mVelocityTracker.clear();
+ mVelocityTracker.addMovement(ev);
+ mInitialTouchPos = getPos(ev);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mCurrView != null) {
+ mVelocityTracker.addMovement(ev);
+ float pos = getPos(ev);
+ float delta = pos - mInitialTouchPos;
+ if (Math.abs(delta) > mPagingTouchSlop) {
+ mCallback.onBeginDrag(mCurrView);
+ mDragging = true;
+ mInitialTouchPos = getPos(ev) - getPos(mCurrView);
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ mDragging = false;
+ mCurrView = null;
+ break;
+ }
+ return mDragging;
+ }
+
+ public void dismissChild(final View animView, float velocity) {
+ float newPos;
+ if (velocity < 0 || (velocity == 0 && getPos(animView) < 0)) {
+ newPos = -getSize(animView);
+ } else {
+ newPos = getSize(animView);
+ }
+ int duration = MAX_ESCAPE_ANIMATION_DURATION;
+ if (velocity != 0) {
+ duration = Math.min(duration,
+ (int) (Math.abs(newPos - getPos(animView)) * 1000f / Math
+ .abs(velocity)));
+ }
+ ObjectAnimator anim = createTranslationAnimation(animView, newPos);
+ anim.setInterpolator(new LinearInterpolator());
+ anim.setDuration(duration);
+ anim.addListener(new AnimatorListener() {
+ public void onAnimationStart(Animator animation) {
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ mCallback.onChildDismissed(animView);
+ }
+
+ public void onAnimationCancel(Animator animation) {
+ mCallback.onChildDismissed(animView);
+ }
+ });
+ anim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (FADE_OUT_DURING_SWIPE) {
+ animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView)));
+ }
+ invalidateGlobalRegion(animView);
+ }
+ });
+ anim.start();
+ }
+
+ public void snapChild(final View animView, float velocity) {
+ ObjectAnimator anim = createTranslationAnimation(animView, 0);
+ int duration = SNAP_ANIM_LEN;
+ anim.setDuration(duration);
+ anim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (FADE_OUT_DURING_SWIPE) {
+ animView.setAlpha(getAlphaForOffset(animView, getContentSize(animView)));
+ }
+ invalidateGlobalRegion(animView);
+ }
+ });
+ anim.start();
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!mDragging) {
+ return false;
+ }
+
+ mVelocityTracker.addMovement(ev);
+ final int action = ev.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_OUTSIDE:
+ case MotionEvent.ACTION_MOVE:
+ if (mCurrView != null) {
+ float delta = getPos(ev) - mInitialTouchPos;
+ // don't let items that can't be dismissed be dragged more than
+ // maxScrollDistance
+ if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
+ float size = getSize(mCurrView);
+ float maxScrollDistance = 0.15f * size;
+ if (Math.abs(delta) >= size) {
+ delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
+ } else {
+ delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
+ }
+ }
+ setTranslation(mCurrView, delta);
+ if (FADE_OUT_DURING_SWIPE) {
+ mCurrView.setAlpha(getAlphaForOffset(mCurrView, getContentSize(mCurrView)));
+ }
+ invalidateGlobalRegion(mCurrView);
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (mCurrView != null) {
+ float maxVelocity = 1000; // px/sec
+ mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity);
+ float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
+ float velocity = getVelocity(mVelocityTracker);
+ float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+
+ // Decide whether to dismiss the current view
+ boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
+ Math.abs(getPos(mCurrView)) > 0.4 * getSize(mCurrView);
+ boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
+ (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
+ (velocity > 0) == (getPos(mCurrView) > 0);
+
+ boolean dismissChild = mCallback.canChildBeDismissed(mCurrView) &&
+ (childSwipedFastEnough || childSwipedFarEnough);
+
+ if (dismissChild) {
+ // flingadingy
+ dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
+ } else {
+ // snappity
+ snapChild(mCurrView, velocity);
+ }
+ }
+ break;
+ }
+ return true;
+ }
+
+ public interface Callback {
+ View getChildAtPosition(MotionEvent ev);
+
+ View getChildContentView(View v);
+
+ boolean canChildBeDismissed(View v);
+
+ void onBeginDrag(View v);
+
+ void onChildDismissed(View v);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
new file mode 100644
index 0000000..723e338
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.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.systemui.net;
+
+import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
+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 android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.INetworkPolicyManager;
+import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+/**
+ * Notify user that a {@link NetworkTemplate} is over its
+ * {@link NetworkPolicy#limitBytes}, giving them the choice of acknowledging or
+ * "snoozing" the limit.
+ */
+public class NetworkOverLimitActivity extends Activity {
+ private static final String TAG = "NetworkOverLimitActivity";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ final NetworkTemplate template = getIntent().getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(getLimitedDialogTitleForTemplate(template));
+ builder.setMessage(R.string.data_usage_disabled_dialog);
+
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.setNegativeButton(
+ R.string.data_usage_disabled_dialog_enable, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ snoozePolicy(template);
+ }
+ });
+
+ final Dialog dialog = builder.create();
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+ });
+
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ dialog.show();
+ }
+
+ private void snoozePolicy(NetworkTemplate template) {
+ final INetworkPolicyManager policyService = INetworkPolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
+ try {
+ policyService.snoozePolicy(template);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "problem snoozing network policy", e);
+ }
+ }
+
+ private static int getLimitedDialogTitleForTemplate(NetworkTemplate template) {
+ switch (template.getMatchRule()) {
+ case MATCH_MOBILE_3G_LOWER:
+ return R.string.data_usage_disabled_dialog_3g_title;
+ case MATCH_MOBILE_4G:
+ return R.string.data_usage_disabled_dialog_4g_title;
+ case MATCH_MOBILE_ALL:
+ return R.string.data_usage_disabled_dialog_mobile_title;
+ default:
+ return R.string.data_usage_disabled_dialog_title;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index a549f51..fe7d5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -45,6 +45,8 @@
public class PowerUI extends SystemUI {
static final String TAG = "PowerUI";
+ static final boolean DEBUG = false;
+
Handler mHandler = new Handler();
int mBatteryLevel = 100;
@@ -122,7 +124,7 @@
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
- if (false) {
+ if (DEBUG) {
Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
@@ -149,8 +151,12 @@
&& (bucket < oldBucket || oldPlugged)
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& bucket < 0) {
- Slog.i(TAG, "showing low battery warning: level=" + mBatteryLevel);
showLowBatteryWarning();
+
+ // only play SFX when the dialog comes up or the bucket changes
+ if (bucket != oldBucket || oldPlugged) {
+ playLowBatterySound();
+ }
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
dismissLowBatteryWarning();
} else if (mBatteryLevelTextView != null) {
@@ -170,6 +176,11 @@
}
void showLowBatteryWarning() {
+ Slog.i(TAG,
+ ((mBatteryLevelTextView == null) ? "showing" : "updating")
+ + " low battery warning: level=" + mBatteryLevel
+ + " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
+
CharSequence levelText = mContext.getString(
R.string.battery_low_percent_format, mBatteryLevel);
@@ -198,9 +209,7 @@
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mContext.startActivity(intent);
- if (mLowBatteryDialog != null) {
- mLowBatteryDialog.dismiss();
- }
+ dismissLowBatteryWarning();
}
});
}
@@ -216,6 +225,12 @@
d.show();
mLowBatteryDialog = d;
}
+ }
+
+ void playLowBatterySound() {
+ if (DEBUG) {
+ Slog.i(TAG, "playing low battery sound. WOMP-WOMP!");
+ }
final ContentResolver cr = mContext.getContentResolver();
if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
@@ -236,12 +251,13 @@
void dismissInvalidChargerDialog() {
if (mInvalidChargerDialog != null) {
- Slog.d(TAG, "closing invalid charger warning");
mInvalidChargerDialog.dismiss();
}
}
void showInvalidChargerDialog() {
+ Slog.d(TAG, "showing invalid charger dialog");
+
dismissLowBatteryWarning();
AlertDialog.Builder b = new AlertDialog.Builder(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
index 797f94c..5609ead 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsCallback.java
@@ -25,6 +25,6 @@
static final int SWIPE_DOWN = 3;
void handleOnClick(View selectedView);
- void handleSwipe(View selectedView, int direction);
+ void handleSwipe(View selectedView);
void handleLongPress(View selectedView, View anchorView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index 2a5d1dd..14efdd0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -16,52 +16,35 @@
package com.android.systemui.recent;
-import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Configuration;
import android.database.DataSetObserver;
-import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-public class RecentsHorizontalScrollView extends HorizontalScrollView {
+public class RecentsHorizontalScrollView extends HorizontalScrollView
+ implements SwipeHelper.Callback {
private static final String TAG = RecentsPanelView.TAG;
- private static final boolean DEBUG_INVALIDATE = false;
private static final boolean DEBUG = RecentsPanelView.DEBUG;
private LinearLayout mLinearLayout;
private ActivityDescriptionAdapter mAdapter;
private RecentsCallback mCallback;
protected int mLastScrollPosition;
- private View mCurrentView;
- private float mLastY;
- private boolean mDragging;
- private VelocityTracker mVelocityTracker;
- private float mDensityScale;
- private float mPagingTouchSlop;
+ private SwipeHelper mSwipeHelper;
private OnLongClickListener mOnLongClick = new OnLongClickListener() {
public boolean onLongClick(View v) {
final View anchorView = v.findViewById(R.id.app_description);
- mCurrentView = v;
mCallback.handleLongPress(v, anchorView);
- mCurrentView = null; // make sure we don't accept the return click from this
return true;
}
};
@@ -72,8 +55,9 @@
public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
- mDensityScale = getResources().getDisplayMetrics().density;
- mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ float densityScale = getResources().getDisplayMetrics().density;
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper = new SwipeHelper(SwipeHelper.Y, this, densityScale, pagingTouchSlop);
}
private int scrollPositionOfMostRecent() {
@@ -84,8 +68,16 @@
mLinearLayout.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
final View view = mAdapter.getView(i, null, mLinearLayout);
- view.setClickable(true);
+ view.setLongClickable(true);
view.setOnLongClickListener(mOnLongClick);
+
+ final View thumbnail = getChildContentView(view);
+ // thumbnail is set to clickable in the layout file
+ thumbnail.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.handleOnClick(view);
+ }
+ });
mLinearLayout.addView(view);
}
// Scroll to end after layout.
@@ -99,175 +91,52 @@
@Override
public void removeViewInLayout(final View view) {
- ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION,
- "y", view.getY(), view.getY() + view.getHeight());
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- RecentsHorizontalScrollView.super.removeView(view);
- }
- });
- anim.start();
+ dismissChild(view);
}
- @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mDragging = false;
- mLastY = ev.getY();
- final float x = ev.getX() + getScrollX();
- final float y = ev.getY() + getScrollY();
- mCurrentView = null;
- for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
- View item = mLinearLayout.getChildAt(i);
- if (x >= item.getLeft() && x < item.getRight()
- && y >= item.getTop() && y < item.getBottom()) {
- mCurrentView = item;
- if (DEBUG) Log.v(TAG, "Hit item " + item);
- break;
- }
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- float delta = ev.getY() - mLastY;
- if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
- if (Math.abs(delta) > mPagingTouchSlop) {
- mDragging = true;
- }
- break;
-
- case MotionEvent.ACTION_UP:
- if (mCurrentView != null) {
- mCallback.handleOnClick(mCurrentView);
- }
- mDragging = false;
- break;
- }
- return mDragging ? true : super.onInterceptTouchEvent(ev);
- }
-
- private float getAlphaForOffset(View view, float thumbHeight) {
- final float fadeHeight = Constants.ALPHA_FADE_END * thumbHeight;
- float result = 1.0f;
- if (view.getY() >= thumbHeight * Constants.ALPHA_FADE_START) {
- result = 1.0f - (view.getY() - thumbHeight * Constants.ALPHA_FADE_START) / fadeHeight;
- } else if (view.getY() < thumbHeight * (1.0f - Constants.ALPHA_FADE_START)) {
- result = 1.0f + (thumbHeight * Constants.ALPHA_FADE_START + view.getY()) / fadeHeight;
- }
- return result;
+ return mSwipeHelper.onInterceptTouchEvent(ev) ||
+ super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (!mDragging) {
- return super.onTouchEvent(ev);
- }
+ return mSwipeHelper.onTouchEvent(ev) ||
+ super.onTouchEvent(ev);
+ }
- mVelocityTracker.addMovement(ev);
-
- final View animView = mCurrentView;
-
- switch (ev.getAction()) {
- case MotionEvent.ACTION_MOVE:
- if (animView != null) {
- final float delta = ev.getY() - mLastY;
- final View thumb = animView.findViewById(R.id.app_thumbnail);
- animView.setY(animView.getY() + delta);
- animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
- invalidateGlobalRegion(animView);
- }
- mLastY = ev.getY();
- break;
-
- case MotionEvent.ACTION_UP:
- final ObjectAnimator anim;
- if (animView != null) {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, 10000);
- final float velocityX = velocityTracker.getXVelocity();
- final float velocityY = velocityTracker.getYVelocity();
- final float curY = animView.getY();
- final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight();
- final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
- if (Math.abs(velocityY) > Math.abs(velocityX)
- && Math.abs(velocityY) > maxVelocity
- && (velocityY >= 0.0f) == (animView.getY() >= 0)) {
- long duration =
- (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY));
- duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
- anim = animateClosed(animView, duration, "y", curY, newY);
- } else { // Animate back to position
- long duration = Math.abs(velocityY) > 0.0f ?
- (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
- : Constants.SNAP_BACK_DURATION;
- duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
- anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f);
- anim.setInterpolator(new DecelerateInterpolator(4.0f));
- anim.setDuration(duration);
- }
-
- final View thumb = animView.findViewById(R.id.app_thumbnail);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- animView.setAlpha(getAlphaForOffset(animView, thumb.getHeight()));
- invalidateGlobalRegion(animView);
- }
- });
- anim.start();
- }
-
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- break;
- }
+ public boolean canChildBeDismissed(View v) {
return true;
}
- private ObjectAnimator animateClosed(final View animView, long duration,
- String attr, float from, float to) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to);
- anim.setInterpolator(new LinearInterpolator());
- final int swipeDirection = animView.getX() >= 0.0f ?
- RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- mLinearLayout.removeView(animView);
- mCallback.handleSwipe(animView, swipeDirection);
- }
- public void onAnimationCancel(Animator animation) {
- mLinearLayout.removeView(animView);
- mCallback.handleSwipe(animView, swipeDirection);
- }
- });
- anim.setDuration(duration);
- return anim;
+ public void dismissChild(View v) {
+ mSwipeHelper.dismissChild(v, 0);
}
- void invalidateGlobalRegion(View view) {
- RectF childBounds
- = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
- childBounds.offset(view.getX(), view.getY());
- if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
- while (view.getParent() != null && view.getParent() instanceof View) {
- view = (View) view.getParent();
- view.getMatrix().mapRect(childBounds);
- view.invalidate((int) Math.floor(childBounds.left),
- (int) Math.floor(childBounds.top),
- (int) Math.ceil(childBounds.right),
- (int) Math.ceil(childBounds.bottom));
- if (DEBUG_INVALIDATE) {
- Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
- + "," + (int) Math.floor(childBounds.top)
- + "," + (int) Math.ceil(childBounds.right)
- + "," + (int) Math.ceil(childBounds.bottom));
+ public void onChildDismissed(View v) {
+ mLinearLayout.removeView(v);
+ mCallback.handleSwipe(v);
+ }
+
+ public void onBeginDrag(View v) {
+ }
+
+ public View getChildAtPosition(MotionEvent ev) {
+ final float x = ev.getX() + getScrollX();
+ final float y = ev.getY() + getScrollY();
+ for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+ View item = mLinearLayout.getChildAt(i);
+ if (x >= item.getLeft() && x < item.getRight()
+ && y >= item.getTop() && y < item.getBottom()) {
+ return item;
}
}
+ return null;
+ }
+
+ public View getChildContentView(View v) {
+ return v.findViewById(R.id.app_thumbnail);
}
@Override
@@ -283,8 +152,10 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- mDensityScale = getResources().getDisplayMetrics().density;
- mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ float densityScale = getResources().getDisplayMetrics().density;
+ mSwipeHelper.setDensityScale(densityScale);
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
}
private void setOverScrollEffectPadding(int leftPadding, int i) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ea54445..c896046 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -45,6 +45,7 @@
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -53,7 +54,6 @@
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
@@ -182,6 +182,15 @@
}
}
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
+ show(false, true);
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
public boolean isInContentArea(int x, int y) {
// use mRecentsContainer's exact bounds to determine horizontal position
final int l = mRecentsContainer.getLeft();
@@ -220,6 +229,11 @@
setVisibility(show ? View.VISIBLE : View.GONE);
mChoreo.jumpTo(show);
}
+ if (show) {
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
}
public void onAnimationCancel(Animator animation) {
@@ -529,7 +543,7 @@
handleOnClick(view);
}
- public void handleSwipe(View view, int direction) {
+ public void handleSwipe(View view) {
ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
mActivityDescriptions.remove(ad);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 47ee4aa..1bcc413 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -16,53 +16,35 @@
package com.android.systemui.recent;
-import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
import android.animation.LayoutTransition;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Configuration;
import android.database.DataSetObserver;
-import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.recent.RecentsPanelView.ActivityDescriptionAdapter;
-public class RecentsVerticalScrollView extends ScrollView {
+public class RecentsVerticalScrollView extends ScrollView implements SwipeHelper.Callback {
private static final String TAG = RecentsPanelView.TAG;
- private static final boolean DEBUG_INVALIDATE = false;
private static final boolean DEBUG = RecentsPanelView.DEBUG;
private LinearLayout mLinearLayout;
private ActivityDescriptionAdapter mAdapter;
private RecentsCallback mCallback;
protected int mLastScrollPosition;
- private View mCurrentView;
- private float mLastX;
- private boolean mDragging;
- private VelocityTracker mVelocityTracker;
- private float mDensityScale;
- private float mPagingTouchSlop;
+ private SwipeHelper mSwipeHelper;
+
private OnLongClickListener mOnLongClick = new OnLongClickListener() {
public boolean onLongClick(View v) {
final View anchorView = v.findViewById(R.id.app_description);
- mCurrentView = v;
mCallback.handleLongPress(v, anchorView);
- mCurrentView = null; // make sure we don't accept the return click from this
return true;
}
};
@@ -73,8 +55,9 @@
public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
- mDensityScale = getResources().getDisplayMetrics().density;
- mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ float densityScale = getResources().getDisplayMetrics().density;
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
}
private int scrollPositionOfMostRecent() {
@@ -87,6 +70,15 @@
final View view = mAdapter.getView(i, null, mLinearLayout);
view.setClickable(true);
view.setOnLongClickListener(mOnLongClick);
+
+ final View thumbnail = getChildContentView(view);
+ // thumbnail is set to clickable in the layout file
+ thumbnail.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.handleOnClick(view);
+ }
+ });
+
mLinearLayout.addView(view);
}
// Scroll to end after layout.
@@ -100,175 +92,52 @@
@Override
public void removeViewInLayout(final View view) {
- ObjectAnimator anim = animateClosed(view, Constants.MAX_ESCAPE_ANIMATION_DURATION,
- "x", view.getX(), view.getX() + view.getWidth());
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- RecentsVerticalScrollView.super.removeView(view);
- }
- });
- anim.start();
+ dismissChild(view);
}
- @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mDragging = false;
- mLastX = ev.getX();
- final float x = ev.getX() + getScrollX();
- final float y = ev.getY() + getScrollY();
- mCurrentView = null;
- for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
- View item = mLinearLayout.getChildAt(i);
- if (x >= item.getLeft() && x < item.getRight()
- && y >= item.getTop() && y < item.getBottom()) {
- mCurrentView = item;
- Log.v(TAG, "Hit item " + item);
- break;
- }
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- float delta = ev.getX() - mLastX;
- if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
- if (Math.abs(delta) > mPagingTouchSlop) {
- mDragging = true;
- }
- break;
-
- case MotionEvent.ACTION_UP:
- if (mCurrentView != null) {
- mCallback.handleOnClick(mCurrentView);
- }
- mDragging = false;
- break;
- }
- return mDragging ? true : super.onInterceptTouchEvent(ev);
- }
-
- private float getAlphaForOffset(View view, float thumbWidth) {
- final float fadeWidth = Constants.ALPHA_FADE_END * thumbWidth;
- float result = 1.0f;
- if (view.getX() >= thumbWidth*Constants.ALPHA_FADE_START) {
- result = 1.0f - (view.getX() - thumbWidth*Constants.ALPHA_FADE_START) / fadeWidth;
- } else if (view.getX() < thumbWidth* (1.0f - Constants.ALPHA_FADE_START)) {
- result = 1.0f + (thumbWidth*Constants.ALPHA_FADE_START + view.getX()) / fadeWidth;
- }
- return result;
+ return mSwipeHelper.onInterceptTouchEvent(ev) ||
+ super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (!mDragging) {
- return super.onTouchEvent(ev);
- }
+ return mSwipeHelper.onTouchEvent(ev) ||
+ super.onTouchEvent(ev);
+ }
- mVelocityTracker.addMovement(ev);
-
- final View animView = mCurrentView;
-
- switch (ev.getAction()) {
- case MotionEvent.ACTION_MOVE:
- if (animView != null) {
- final float delta = ev.getX() - mLastX;
- final View thumb = animView.findViewById(R.id.app_thumbnail);
- animView.setX(animView.getX() + delta);
- animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
- invalidateGlobalRegion(animView);
- }
- mLastX = ev.getX();
- break;
-
- case MotionEvent.ACTION_UP:
- final ObjectAnimator anim;
- if (animView != null) {
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, 10000);
- final float velocityX = velocityTracker.getXVelocity();
- final float velocityY = velocityTracker.getYVelocity();
- final float curX = animView.getX();
- final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth();
- final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
- if (Math.abs(velocityX) > Math.abs(velocityY)
- && Math.abs(velocityX) > maxVelocity
- && (velocityX >= 0.0f) == (animView.getX() >= 0)) {
- long duration =
- (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX));
- duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
- anim = animateClosed(animView, duration, "x", curX, newX);
- } else { // Animate back to position
- long duration = Math.abs(velocityX) > 0.0f ?
- (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
- : Constants.SNAP_BACK_DURATION;
- duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
- anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f);
- anim.setInterpolator(new DecelerateInterpolator(4.0f));
- anim.setDuration(duration);
- }
-
- final View thumb = animView.findViewById(R.id.app_thumbnail);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- animView.setAlpha(getAlphaForOffset(animView, thumb.getWidth()));
- invalidateGlobalRegion(animView);
- }
- });
- anim.start();
- }
-
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- break;
- }
+ public boolean canChildBeDismissed(View v) {
return true;
}
- private ObjectAnimator animateClosed(final View animView, long duration,
- String attr, float from, float to) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(animView, attr, from, to);
- anim.setInterpolator(new LinearInterpolator());
- final int swipeDirection = animView.getX() >= 0.0f ?
- RecentsCallback.SWIPE_RIGHT : RecentsCallback.SWIPE_LEFT;
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- mLinearLayout.removeView(animView);
- mCallback.handleSwipe(animView, swipeDirection);
- }
- public void onAnimationCancel(Animator animation) {
- mLinearLayout.removeView(animView);
- mCallback.handleSwipe(animView, swipeDirection);
- }
- });
- anim.setDuration(duration);
- return anim;
+ public void dismissChild(View v) {
+ mSwipeHelper.dismissChild(v, 0);
}
- void invalidateGlobalRegion(View view) {
- RectF childBounds
- = new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
- childBounds.offset(view.getX(), view.getY());
- if (DEBUG_INVALIDATE) Log.v(TAG, "-------------");
- while (view.getParent() != null && view.getParent() instanceof View) {
- view = (View) view.getParent();
- view.getMatrix().mapRect(childBounds);
- view.invalidate((int) Math.floor(childBounds.left),
- (int) Math.floor(childBounds.top),
- (int) Math.ceil(childBounds.right),
- (int) Math.ceil(childBounds.bottom));
- if (DEBUG_INVALIDATE) {
- Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
- + "," + (int) Math.floor(childBounds.top)
- + "," + (int) Math.ceil(childBounds.right)
- + "," + (int) Math.ceil(childBounds.bottom));
+ public void onChildDismissed(View v) {
+ mLinearLayout.removeView(v);
+ mCallback.handleSwipe(v);
+ }
+
+ public void onBeginDrag(View v) {
+ }
+
+ public View getChildAtPosition(MotionEvent ev) {
+ final float x = ev.getX() + getScrollX();
+ final float y = ev.getY() + getScrollY();
+ for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+ View item = mLinearLayout.getChildAt(i);
+ if (x >= item.getLeft() && x < item.getRight()
+ && y >= item.getTop() && y < item.getBottom()) {
+ return item;
}
}
+ return null;
+ }
+
+ public View getChildContentView(View v) {
+ return v.findViewById(R.id.app_thumbnail);
}
@Override
@@ -284,8 +153,10 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- mDensityScale = getResources().getDisplayMetrics().density;
- mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ float densityScale = getResources().getDisplayMetrics().density;
+ mSwipeHelper.setDensityScale(densityScale);
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
}
private void setOverScrollEffectPadding(int leftPadding, int i) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 83a5578..3a47e6e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -24,6 +24,7 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
@@ -78,7 +79,8 @@
SaveImageInBackgroundData> {
private static final String TAG = "SaveImageInBackgroundTask";
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
- private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/Screenshot_%s-%d.png";
+ private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+ private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
@Override
protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
@@ -87,34 +89,41 @@
Context context = params[0].context;
Bitmap image = params[0].image;
- try{
+ try {
long currentTime = System.currentTimeMillis();
- String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
+ String date = new SimpleDateFormat("yyyy-MM-dd-kk-mm-ss").format(new Date(currentTime));
String imageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getAbsolutePath();
- String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE,
- imageDir, SCREENSHOTS_DIR_NAME,
- date, currentTime % 1000);
+ String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date);
+ String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir,
+ SCREENSHOTS_DIR_NAME, imageFileName);
// Save the screenshot to the MediaStore
ContentValues values = new ContentValues();
+ ContentResolver resolver = context.getContentResolver();
values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath);
- values.put(MediaStore.Images.ImageColumns.TITLE, "Screenshot");
- values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, "Screenshot");
+ values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName);
+ values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName);
values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime);
values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime);
values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime);
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
- Uri uri = context.getContentResolver().insert(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+ Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
- OutputStream out = context.getContentResolver().openOutputStream(uri);
+ OutputStream out = resolver.openOutputStream(uri);
image.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
+ // update file size in the database
+ values.clear();
+ values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length());
+ resolver.update(uri, values, null, null);
+
params[0].result = 0;
- }catch(IOException e){
+ } catch (Exception e) {
+ // IOException/UnsupportedOperationException may be thrown if external storage is not
+ // mounted
params[0].result = 1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index be4b395..1e27233 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -58,6 +58,14 @@
mNumberPain.setAntiAlias(true);
mNotification = notification;
setContentDescription(notification);
+
+ final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+ final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+ final float scale = (float)imageBounds / (float)outerBounds;
+ setScaleX(scale);
+ setScaleY(scale);
+ final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
+ setAlpha(alpha);
}
private static boolean streq(String a, String b) {
@@ -99,6 +107,7 @@
if (!levelEquals) {
setImageLevel(icon.iconLevel);
}
+
if (!numberEquals) {
if (icon.number > 0 && mContext.getResources().getBoolean(
R.bool.config_statusBarShowNumber)) {
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 b93ad68..21b774c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -82,7 +82,9 @@
import com.android.systemui.statusbar.StatusBar;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.DateView;
-
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.NetworkController;
public class PhoneStatusBar extends StatusBar {
static final String TAG = "PhoneStatusBar";
@@ -107,6 +109,11 @@
PhoneStatusBarPolicy mIconPolicy;
+ // These are no longer handled by the policy, because we need custom strategies for them
+ BatteryController mBatteryController;
+ LocationController mLocationController;
+ NetworkController mNetworkController;
+
int mIconSize;
Display mDisplay;
@@ -306,6 +313,32 @@
setAreThereNotifications();
mDateView.setVisibility(View.INVISIBLE);
+ // Other icons
+ mLocationController = new LocationController(mContext); // will post a notification
+ mBatteryController = new BatteryController(mContext);
+ mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
+ mNetworkController = new NetworkController(mContext);
+ final ImageView comboRSSI =
+ (ImageView)sb.findViewById(R.id.network_signal);
+ if (comboRSSI != null) {
+ mNetworkController.addCombinedSignalIconView(comboRSSI);
+ }
+ final ImageView mobileRSSI =
+ (ImageView)sb.findViewById(R.id.mobile_signal);
+ if (mobileRSSI != null) {
+ mNetworkController.addPhoneSignalIconView(mobileRSSI);
+ }
+ final ImageView wifiRSSI =
+ (ImageView)sb.findViewById(R.id.wifi_signal);
+ if (wifiRSSI != null) {
+ mNetworkController.addWifiIconView(wifiRSSI);
+ }
+ mNetworkController.addDataTypeIconView(
+ (ImageView)sb.findViewById(R.id.network_type));
+ mNetworkController.addDataDirectionOverlayIconView(
+ (ImageView)sb.findViewById(R.id.network_direction));
+ mNetworkController.setStackedMode(true);
+
// Recents Panel
updateRecentsPanel();
@@ -612,6 +645,14 @@
handleNotificationError(key, notification, "Couldn't update icon: " + ic);
return;
}
+ // Update the large icon
+ if (notification.notification.largeIcon != null) {
+ oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
+ } else {
+ oldEntry.largeIcon.getLayoutParams().width = 0;
+ oldEntry.largeIcon.setVisibility(View.INVISIBLE);
+ }
+
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 7b50985..322a8c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -38,7 +38,6 @@
import android.telephony.TelephonyManager;
import android.util.Slog;
-import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.cdma.EriInfo;
@@ -68,403 +67,14 @@
private final Context mContext;
private final StatusBarManager mService;
private final Handler mHandler = new Handler();
- private final IBatteryStats mBatteryStats;
// storage
private StorageManager mStorageManager;
- // phone
- private TelephonyManager mPhone;
- private int mPhoneSignalIconId;
-
- //***** Signal strength icons
- //GSM/UMTS
- private static final int[][] sSignalImages = {
- { R.drawable.stat_sys_signal_0,
- R.drawable.stat_sys_signal_1,
- R.drawable.stat_sys_signal_2,
- R.drawable.stat_sys_signal_3,
- R.drawable.stat_sys_signal_4 },
- { R.drawable.stat_sys_signal_0_fully,
- R.drawable.stat_sys_signal_1_fully,
- R.drawable.stat_sys_signal_2_fully,
- R.drawable.stat_sys_signal_3_fully,
- R.drawable.stat_sys_signal_4_fully }
- };
- private static final int[][] sSignalImages_r = {
- { R.drawable.stat_sys_r_signal_0,
- R.drawable.stat_sys_r_signal_1,
- R.drawable.stat_sys_r_signal_2,
- R.drawable.stat_sys_r_signal_3,
- R.drawable.stat_sys_r_signal_4 },
- { R.drawable.stat_sys_r_signal_0_fully,
- R.drawable.stat_sys_r_signal_1_fully,
- R.drawable.stat_sys_r_signal_2_fully,
- R.drawable.stat_sys_r_signal_3_fully,
- R.drawable.stat_sys_r_signal_4_fully }
- };
- private static final int[] sRoamingIndicatorImages_cdma = new int[] {
- R.drawable.stat_sys_roaming_cdma_0, //Standard Roaming Indicator
- // 1 is Standard Roaming Indicator OFF
- // TODO T: image never used, remove and put 0 instead?
- R.drawable.stat_sys_roaming_cdma_0,
-
- // 2 is Standard Roaming Indicator FLASHING
- // TODO T: image never used, remove and put 0 instead?
- R.drawable.stat_sys_roaming_cdma_0,
-
- // 3-12 Standard ERI
- R.drawable.stat_sys_roaming_cdma_0, //3
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
-
- // 13-63 Reserved for Standard ERI
- R.drawable.stat_sys_roaming_cdma_0, //13
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
-
- // 64-127 Reserved for Non Standard (Operator Specific) ERI
- R.drawable.stat_sys_roaming_cdma_0, //64
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0, //83
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0,
- R.drawable.stat_sys_roaming_cdma_0 //239
-
- // 240-255 Reserved
- };
-
- //***** Data connection icons
- private int[] mDataIconList = sDataNetType_g[0];
- //GSM/UMTS
- private static final int[][] sDataNetType_g = {
- { R.drawable.stat_sys_data_connected_g,
- R.drawable.stat_sys_data_in_g,
- R.drawable.stat_sys_data_out_g,
- R.drawable.stat_sys_data_inandout_g },
- { R.drawable.stat_sys_data_fully_connected_g,
- R.drawable.stat_sys_data_fully_in_g,
- R.drawable.stat_sys_data_fully_out_g,
- R.drawable.stat_sys_data_fully_inandout_g }
- };
- private static final int[][] sDataNetType_3g = {
- { R.drawable.stat_sys_data_connected_3g,
- R.drawable.stat_sys_data_in_3g,
- R.drawable.stat_sys_data_out_3g,
- R.drawable.stat_sys_data_inandout_3g },
- { R.drawable.stat_sys_data_fully_connected_3g,
- R.drawable.stat_sys_data_fully_in_3g,
- R.drawable.stat_sys_data_fully_out_3g,
- R.drawable.stat_sys_data_fully_inandout_3g }
- };
- private static final int[][] sDataNetType_4g = {
- { R.drawable.stat_sys_data_connected_4g,
- R.drawable.stat_sys_data_in_4g,
- R.drawable.stat_sys_data_out_4g,
- R.drawable.stat_sys_data_inandout_4g },
- { R.drawable.stat_sys_data_fully_connected_4g,
- R.drawable.stat_sys_data_fully_in_4g,
- R.drawable.stat_sys_data_fully_out_4g,
- R.drawable.stat_sys_data_fully_inandout_4g }
- };
- private static final int[][] sDataNetType_e = {
- { R.drawable.stat_sys_data_connected_e,
- R.drawable.stat_sys_data_in_e,
- R.drawable.stat_sys_data_out_e,
- R.drawable.stat_sys_data_inandout_e },
- { R.drawable.stat_sys_data_fully_connected_e,
- R.drawable.stat_sys_data_fully_in_e,
- R.drawable.stat_sys_data_fully_out_e,
- R.drawable.stat_sys_data_fully_inandout_e }
- };
- //3.5G
- private static final int[][] sDataNetType_h = {
- { R.drawable.stat_sys_data_connected_h,
- R.drawable.stat_sys_data_in_h,
- R.drawable.stat_sys_data_out_h,
- R.drawable.stat_sys_data_inandout_h },
- { R.drawable.stat_sys_data_fully_connected_h,
- R.drawable.stat_sys_data_fully_in_h,
- R.drawable.stat_sys_data_fully_out_h,
- R.drawable.stat_sys_data_fully_inandout_h }
- };
-
- //CDMA
- // Use 3G icons for EVDO data and 1x icons for 1XRTT data
- private static final int[][] sDataNetType_1x = {
- { R.drawable.stat_sys_data_connected_1x,
- R.drawable.stat_sys_data_in_1x,
- R.drawable.stat_sys_data_out_1x,
- R.drawable.stat_sys_data_inandout_1x },
- { R.drawable.stat_sys_data_fully_connected_1x,
- R.drawable.stat_sys_data_fully_in_1x,
- R.drawable.stat_sys_data_fully_out_1x,
- R.drawable.stat_sys_data_fully_inandout_1x }
- };
-
- // Accessibility;
-
- private static final int[] sPhoneSignalStrength = {
- R.string.accessibility_no_phone,
- R.string.accessibility_phone_one_bar,
- R.string.accessibility_phone_two_bars,
- R.string.accessibility_phone_three_bars,
- R.string.accessibility_phone_signal_full
- };
-
- private static final int[] sDataConnectionStrength = {
- R.string.accessibility_no_data,
- R.string.accessibility_data_one_bar,
- R.string.accessibility_data_two_bars,
- R.string.accessibility_data_three_bars,
- R.string.accessibility_data_signal_full
- };
-
- private static final int[] sWifiConnectionStrength = {
- R.string.accessibility_no_wifi,
- R.string.accessibility_wifi_one_bar,
- R.string.accessibility_wifi_two_bars,
- R.string.accessibility_wifi_three_bars,
- R.string.accessibility_wifi_signal_full
- };
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
IccCard.State mSimState = IccCard.State.READY;
- int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
- int mDataState = TelephonyManager.DATA_DISCONNECTED;
- int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
- ServiceState mServiceState;
- SignalStrength mSignalStrength;
-
- // data connection
- private boolean mDataIconVisible;
- private boolean mHspaDataDistinguishable;
// ringer volume
private boolean mVolumeVisible;
@@ -500,10 +110,7 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- updateBattery(intent);
- }
- else if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
+ if (action.equals(Intent.ACTION_ALARM_CHANGED)) {
updateAlarm(intent);
}
else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) {
@@ -513,15 +120,6 @@
action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
updateBluetooth(intent);
}
- else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION) ||
- action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) ||
- action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
- updateWifi(intent);
- }
- else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) ||
- action.equals(LocationManager.GPS_FIX_CHANGE_ACTION)) {
- updateGps(intent);
- }
else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
action.equals(AudioManager.VIBRATE_SETTING_CHANGED_ACTION)) {
updateVolume();
@@ -532,52 +130,18 @@
else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
updateTTY(intent);
}
- else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
- action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
- // TODO - stop using other means to get wifi/mobile info
- updateConnectivity(intent);
- }
}
};
public PhoneStatusBarPolicy(Context context) {
mContext = context;
mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
- mSignalStrength = new SignalStrength();
- mBatteryStats = BatteryStatsService.getService();
// storage
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
mStorageManager.registerListener(
new com.android.systemui.usb.StorageNotification(context));
- // battery
- mService.setIcon("battery", com.android.internal.R.drawable.stat_sys_battery_unknown, 0,
- null);
-
- // phone_signal
- mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
- mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null);
-
- // register for phone state notifications.
- ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
- .listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_SERVICE_STATE
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
- | PhoneStateListener.LISTEN_CALL_STATE
- | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
- | PhoneStateListener.LISTEN_DATA_ACTIVITY);
-
- // data_connection
- mService.setIcon("data_connection", R.drawable.stat_sys_data_connected_g, 0, null);
- mService.setIconVisibility("data_connection", false);
-
- // wifi
- mService.setIcon("wifi", sWifiSignalImages[0][0], 0, null);
- mService.setIconVisibility("wifi", false);
- // wifi will get updated by the sticky intents
-
// TTY status
mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null);
mService.setIconVisibility("tty", false);
@@ -596,10 +160,6 @@
}
mService.setIconVisibility("bluetooth", mBluetoothEnabled);
- // Gps status
- mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0, null);
- mService.setIconVisibility("gps", false);
-
// Alarm clock
mService.setIcon("alarm_clock", R.drawable.stat_notify_alarm, 0, null);
mService.setIconVisibility("alarm_clock", false);
@@ -620,32 +180,15 @@
IntentFilter filter = new IntentFilter();
// Register for Intent broadcasts for...
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_ALARM_CHANGED);
filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
- filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
- filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
- filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
- filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
-
- // load config to determine if to distinguish Hspa data icon
- try {
- mHspaDataDistinguishable = mContext.getResources().getBoolean(
- R.bool.config_hspa_data_distinguishable);
- } catch (Exception e) {
- mHspaDataDistinguishable = false;
- }
}
private final void updateAlarm(Intent intent) {
@@ -661,96 +204,6 @@
//mService.setIconVisibility("sync_failing", isFailing && !isActive);
}
- private final void updateBattery(Intent intent) {
- final int id = intent.getIntExtra("icon-small", 0);
- int level = intent.getIntExtra("level", 0);
- String contentDescription = mContext.getString(R.string.accessibility_battery_level, level);
- mService.setIcon("battery", id, level, contentDescription);
- }
-
- private void updateConnectivity(Intent intent) {
- NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
- ConnectivityManager.EXTRA_NETWORK_INFO));
- int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
-
- int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
-
- switch (info.getType()) {
- case ConnectivityManager.TYPE_MOBILE:
- mInetCondition = inetCondition;
- updateDataNetType(info.getSubtype());
- updateDataIcon();
- updateSignalStrength(); // apply any change in connectionStatus
- break;
- case ConnectivityManager.TYPE_WIFI:
- mInetCondition = inetCondition;
- if (info.isConnected()) {
- mIsWifiConnected = true;
- int iconId;
- String contentDescription = null;
- if (mLastWifiSignalLevel == -1) {
- iconId = sWifiSignalImages[mInetCondition][0];
- contentDescription = mContext.getString(sWifiConnectionStrength[0]);
- } else {
- iconId = sWifiSignalImages[mInetCondition][mLastWifiSignalLevel];
- contentDescription = mContext.getString(
- sWifiConnectionStrength[mLastWifiSignalLevel]);
- }
- mService.setIcon("wifi", iconId, 0, contentDescription);
- // Show the icon since wi-fi is connected
- mService.setIconVisibility("wifi", true);
- } else {
- mLastWifiSignalLevel = -1;
- mIsWifiConnected = false;
- int iconId = sWifiSignalImages[0][0];
-
- String contentDescription = mContext.getString(R.string.accessibility_no_wifi);
- mService.setIcon("wifi", iconId, 0, contentDescription);
- // Hide the icon since we're not connected
- mService.setIconVisibility("wifi", false);
- }
- updateSignalStrength(); // apply any change in mInetCondition
- break;
- }
- }
-
- private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- mSignalStrength = signalStrength;
- updateSignalStrength();
- }
-
- @Override
- public void onServiceStateChanged(ServiceState state) {
- mServiceState = state;
- updateSignalStrength();
- updateCdmaRoamingIcon(state);
- updateDataIcon();
- }
-
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- // In cdma, if a voice call is made, RSSI should switch to 1x.
- if (isCdma()) {
- updateSignalStrength();
- }
- }
-
- @Override
- public void onDataConnectionStateChanged(int state, int networkType) {
- mDataState = state;
- updateDataNetType(networkType);
- updateDataIcon();
- }
-
- @Override
- public void onDataActivity(int direction) {
- mDataActivity = direction;
- updateDataIcon();
- }
- };
-
private final void updateSimState(Intent intent) {
String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
@@ -773,171 +226,6 @@
} else {
mSimState = IccCard.State.UNKNOWN;
}
- updateDataIcon();
- }
-
- private boolean isCdma() {
- return (mSignalStrength != null) && !mSignalStrength.isGsm();
- }
-
- private boolean hasService() {
- if (mServiceState != null) {
- switch (mServiceState.getState()) {
- case ServiceState.STATE_OUT_OF_SERVICE:
- case ServiceState.STATE_POWER_OFF:
- return false;
- default:
- return true;
- }
- } else {
- return false;
- }
- }
-
- private final void updateSignalStrength() {
- int[] iconList;
- String contentDescription = null;
-
- // Display signal strength while in "emergency calls only" mode
- if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) {
- //Slog.d(TAG, "updateSignalStrength: no service");
- if (Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
- mPhoneSignalIconId = R.drawable.stat_sys_signal_flightmode;
- contentDescription = mContext.getString(R.string.accessibility_airplane_mode);
- } else {
- mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
- contentDescription = mContext.getString(R.string.accessibility_no_phone);
- }
- mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription);
- return;
- }
-
- if (!isCdma()) {
- // Though mPhone is a Manager, this call is not an IPC
- if (mPhone.isNetworkRoaming()) {
- iconList = sSignalImages_r[mInetCondition];
- } else {
- iconList = sSignalImages[mInetCondition];
- }
- } else {
- iconList = sSignalImages[mInetCondition];
- }
-
- final int signalLevel = mSignalStrength.getLevel();
- mPhoneSignalIconId = iconList[signalLevel];
- contentDescription = mContext.getString(sPhoneSignalStrength[signalLevel]);
- mService.setIcon("phone_signal", mPhoneSignalIconId, 0, contentDescription);
- }
-
- private final void updateDataNetType(int net) {
- switch (net) {
- case TelephonyManager.NETWORK_TYPE_EDGE:
- mDataIconList = sDataNetType_e[mInetCondition];
- break;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- mDataIconList = sDataNetType_3g[mInetCondition];
- break;
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- if (mHspaDataDistinguishable) {
- mDataIconList = sDataNetType_h[mInetCondition];
- } else {
- mDataIconList = sDataNetType_3g[mInetCondition];
- }
- break;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- // display 1xRTT for IS95A/B
- mDataIconList = sDataNetType_1x[mInetCondition];
- break;
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- mDataIconList = sDataNetType_1x[mInetCondition];
- break;
- case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- mDataIconList = sDataNetType_3g[mInetCondition];
- break;
- case TelephonyManager.NETWORK_TYPE_LTE:
- mDataIconList = sDataNetType_4g[mInetCondition];
- break;
- default:
- mDataIconList = sDataNetType_g[mInetCondition];
- break;
- }
- }
-
- private final void updateDataIcon() {
- int iconId;
- String contentDescription = null;
- boolean visible = true;
-
- if (!isCdma()) {
- // GSM case, we have to check also the sim state
- if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
- if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
- switch (mDataActivity) {
- case TelephonyManager.DATA_ACTIVITY_IN:
- iconId = mDataIconList[1];
- break;
- case TelephonyManager.DATA_ACTIVITY_OUT:
- iconId = mDataIconList[2];
- break;
- case TelephonyManager.DATA_ACTIVITY_INOUT:
- iconId = mDataIconList[3];
- break;
- default:
- iconId = mDataIconList[0];
- break;
- }
- contentDescription = mContext.getString(sDataConnectionStrength[mDataActivity]);
- mService.setIcon("data_connection", iconId, 0, contentDescription);
- } else {
- visible = false;
- }
- } else {
- iconId = R.drawable.stat_sys_no_sim;
- contentDescription = mContext.getString(R.string.accessibility_no_sim);
- mService.setIcon("data_connection", iconId, 0, contentDescription);
- }
- } else {
- // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
- if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
- switch (mDataActivity) {
- case TelephonyManager.DATA_ACTIVITY_IN:
- iconId = mDataIconList[1];
- break;
- case TelephonyManager.DATA_ACTIVITY_OUT:
- iconId = mDataIconList[2];
- break;
- case TelephonyManager.DATA_ACTIVITY_INOUT:
- iconId = mDataIconList[3];
- break;
- case TelephonyManager.DATA_ACTIVITY_DORMANT:
- default:
- iconId = mDataIconList[0];
- break;
- }
- mService.setIcon("data_connection", iconId, 0, null);
- } else {
- visible = false;
- }
- }
-
- long ident = Binder.clearCallingIdentity();
- try {
- mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- if (mDataIconVisible != visible) {
- mService.setIconVisibility("data_connection", visible);
- mDataIconVisible = visible;
- }
}
private final void updateVolume() {
@@ -990,65 +278,6 @@
mService.setIconVisibility("bluetooth", mBluetoothEnabled);
}
- private final void updateWifi(Intent intent) {
- final String action = intent.getAction();
- if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-
- final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
- if (!enabled) {
- // If disabled, hide the icon. (We show icon when connected.)
- mService.setIconVisibility("wifi", false);
- }
-
- } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
- final boolean enabled = intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED,
- false);
- if (!enabled) {
- mService.setIconVisibility("wifi", false);
- }
- } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
- int iconId;
- String contentDescription = null;
- final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
- int newSignalLevel = WifiManager.calculateSignalLevel(newRssi,
- sWifiSignalImages[0].length);
- if (newSignalLevel != mLastWifiSignalLevel) {
- mLastWifiSignalLevel = newSignalLevel;
- if (mIsWifiConnected) {
- iconId = sWifiSignalImages[mInetCondition][newSignalLevel];
- contentDescription = mContext.getString(
- sWifiConnectionStrength[newSignalLevel]);
- } else {
- iconId = sWifiTemporarilyNotConnectedImage;
- contentDescription = mContext.getString(R.string.accessibility_no_wifi);
- }
- mService.setIcon("wifi", iconId, 0, contentDescription);
- }
- }
- }
-
- private final void updateGps(Intent intent) {
- final String action = intent.getAction();
- final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
-
- if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
- // GPS is getting fixes
- mService.setIcon("gps", com.android.internal.R.drawable.stat_sys_gps_on, 0,
- mContext.getString(R.string.accessibility_gps_enabled));
- mService.setIconVisibility("gps", true);
- } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
- // GPS is off
- mService.setIconVisibility("gps", false);
- } else {
- // GPS is on, but not receiving fixes
- mService.setIcon("gps", R.drawable.stat_sys_gps_acquiring_anim, 0,
- mContext.getString(R.string.accessibility_gps_acquiring));
- mService.setIconVisibility("gps", true);
- }
- }
-
private final void updateTTY(Intent intent) {
final String action = intent.getAction();
final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
@@ -1067,49 +296,4 @@
mService.setIconVisibility("tty", false);
}
}
-
- private final void updateCdmaRoamingIcon(ServiceState state) {
- if (!hasService()) {
- mService.setIconVisibility("cdma_eri", false);
- return;
- }
-
- if (!isCdma()) {
- mService.setIconVisibility("cdma_eri", false);
- return;
- }
-
- int[] iconList = sRoamingIndicatorImages_cdma;
- int iconIndex = state.getCdmaEriIconIndex();
- int iconMode = state.getCdmaEriIconMode();
-
- if (iconIndex == -1) {
- Slog.e(TAG, "getCdmaEriIconIndex returned null, skipping ERI icon update");
- return;
- }
-
- if (iconMode == -1) {
- Slog.e(TAG, "getCdmeEriIconMode returned null, skipping ERI icon update");
- return;
- }
-
- if (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) {
- if (false) Slog.v(TAG, "Cdma ROAMING_INDICATOR_OFF, removing ERI icon");
- mService.setIconVisibility("cdma_eri", false);
- return;
- }
-
- switch (iconMode) {
- case EriInfo.ROAMING_ICON_MODE_NORMAL:
- mService.setIcon("cdma_eri", iconList[iconIndex], 0, null);
- mService.setIconVisibility("cdma_eri", true);
- break;
- case EriInfo.ROAMING_ICON_MODE_FLASH:
- mService.setIcon("cdma_eri", R.drawable.stat_sys_roaming_cdma_flash, 0, null);
- mService.setIconVisibility("cdma_eri", true);
- break;
-
- }
- mService.setIcon("phone_signal", mPhoneSignalIconId, 0, null);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 3957c1b..ff418c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -56,9 +56,11 @@
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+ final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+ final int icon = plugged ? R.drawable.stat_sys_battery_charge
+ : R.drawable.stat_sys_battery;
int N = mIconViews.size();
for (int i=0; i<N; i++) {
- final int icon = intent.getIntExtra(BatteryManager.EXTRA_ICON_SMALL, 0);
ImageView v = mIconViews.get(i);
v.setImageResource(icon);
v.setImageLevel(level);
@@ -67,7 +69,6 @@
}
N = mLabelViews.size();
for (int i=0; i<N; i++) {
- //final boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
TextView v = mLabelViews.get(i);
v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format,
level));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 829855b..f32c602 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -127,6 +127,8 @@
int mLastDataTypeIconId = -1;
String mLastLabel = "";
+ boolean mDataAndWifiStacked = false;
+
// yuck -- stop doing this here and put it in the framework
IBatteryStats mBatteryStats;
@@ -211,6 +213,10 @@
mLabelViews.add(v);
}
+ public void setStackedMode(boolean stacked) {
+ mDataAndWifiStacked = true;
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
@@ -648,7 +654,11 @@
mContentDescriptionWifi = mContext.getString(
AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
} else {
- mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
+ if (mDataAndWifiStacked) {
+ mWifiIconId = 0;
+ } else {
+ mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[0][0];
+ }
mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
}
}
@@ -823,8 +833,13 @@
N = mWifiIconViews.size();
for (int i=0; i<N; i++) {
final ImageView v = mWifiIconViews.get(i);
- v.setImageResource(mWifiIconId);
- v.setContentDescription(mContentDescriptionWifi);
+ if (mWifiIconId == 0) {
+ v.setVisibility(View.INVISIBLE);
+ } else {
+ v.setVisibility(View.VISIBLE);
+ v.setImageResource(mWifiIconId);
+ v.setContentDescription(mContentDescriptionWifi);
+ }
}
}
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 d5885bb..90234c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -21,47 +21,33 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
-import android.animation.ValueAnimator;
import android.content.Context;
-import android.content.res.Resources;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
-import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Slog;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
import java.util.HashSet;
-import com.android.systemui.R;
-
-public class NotificationRowLayout extends ViewGroup {
+public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Callback {
private static final String TAG = "NotificationRowLayout";
private static final boolean DEBUG = false;
private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
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;
@@ -71,10 +57,7 @@
HashSet<View> mAppearingViews = new HashSet<View>();
HashSet<View> mDisappearingViews = new HashSet<View>();
- VelocityTracker mVT;
- float mInitialTouchX, mInitialTouchY;
- View mSlidingChild = null;
- float mLiftoffVelocity;
+ private SwipeHelper mSwipeHelper;
public NotificationRowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -83,8 +66,6 @@
public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mVT = VelocityTracker.obtain();
-
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationRowLayout,
defStyle, 0);
mRowHeight = a.getDimensionPixelSize(R.styleable.NotificationRowLayout_rowHeight, 0);
@@ -107,117 +88,71 @@
setBackgroundColor(0x80FF8000);
}
+ float densityScale = getResources().getDisplayMetrics().density;
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
}
- // Swipey code
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
-// if (DEBUG) Slog.d(TAG, "intercepting touch event: " + ev);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mVT.clear();
- mVT.addMovement(ev);
- mInitialTouchX = ev.getX();
- mInitialTouchY = ev.getY();
- mSlidingChild = null;
- break;
- case MotionEvent.ACTION_MOVE:
- mVT.addMovement(ev);
- if (mSlidingChild == null) {
- if (Math.abs(ev.getX() - mInitialTouchX) > 4) { // slide slop
-
- // find the view under the pointer, accounting for GONE views
- final int count = getChildCount();
- int y = 0;
- int childIdx = 0;
- for (; childIdx < count; childIdx++) {
- mSlidingChild = getChildAt(childIdx);
- if (mSlidingChild.getVisibility() == GONE) {
- continue;
- }
- y += mRowHeight;
- if (mInitialTouchY < y) break;
- }
-
- mInitialTouchX -= mSlidingChild.getTranslationX();
- mSlidingChild.animate().cancel();
-
- if (DEBUG) {
- Slog.d(TAG, String.format(
- "now sliding child %d: %s (touchY=%.1f, rowHeight=%d, count=%d)",
- childIdx, mSlidingChild, mInitialTouchY, mRowHeight, count));
- }
-
-
- // We need to prevent the surrounding ScrollView from intercepting us now;
- // the scroll position will be locked while we swipe
- requestDisallowInterceptTouchEvent(true);
- }
- }
- break;
- }
- 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;
+ if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
+ return mSwipeHelper.onInterceptTouchEvent(ev) ||
+ super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
- final int action = ev.getAction();
-// if (DEBUG) Slog.d(TAG, "touch event: " + ev + " sliding: " + mSlidingChild);
- if (mSlidingChild != null) {
- switch (action) {
- case MotionEvent.ACTION_OUTSIDE:
- case MotionEvent.ACTION_MOVE:
- mVT.addMovement(ev);
+ return mSwipeHelper.onTouchEvent(ev) ||
+ super.onTouchEvent(ev);
+ }
- 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:
- mVT.addMovement(ev);
- mVT.computeCurrentVelocity(1000 /* px/sec */);
- if (DEBUG) Slog.d(TAG, "exit velocity: " + mVT.getXVelocity());
- boolean restore = true;
- mLiftoffVelocity = mVT.getXVelocity();
- if (Math.abs(mLiftoffVelocity) > SWIPE_ESCAPE_VELOCITY
- || (CLEAR_IF_SWIPED_FAR_ENOUGH &&
- (mSlidingChild.getTranslationX() * 2) > mSlidingChild.getMeasuredWidth()))
- {
+ public boolean canChildBeDismissed(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ return (veto != null && veto.getVisibility() != View.GONE);
+ }
- // flingadingy
- restore = ! clear(mSlidingChild);
- }
- if (restore) {
- // snappity
- mSlidingChild.animate().translationX(0)
- .setDuration(SNAP_ANIM_LEN)
- .start();
- }
- break;
- }
- return true;
+ public void onChildDismissed(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ if (veto != null && veto.getVisibility() != View.GONE) {
+ veto.performClick();
}
- return false;
+ }
+
+ public void onBeginDrag(View v) {
+ // We need to prevent the surrounding ScrollView from intercepting us now;
+ // the scroll position will be locked while we swipe
+ requestDisallowInterceptTouchEvent(true);
+ }
+
+ public View getChildAtPosition(MotionEvent ev) {
+ // find the view under the pointer, accounting for GONE views
+ final int count = getChildCount();
+ int y = 0;
+ int touchY = (int) ev.getY();
+ int childIdx = 0;
+ View slidingChild;
+ for (; childIdx < count; childIdx++) {
+ slidingChild = getChildAt(childIdx);
+ if (slidingChild.getVisibility() == GONE) {
+ continue;
+ }
+ y += mRowHeight;
+ if (touchY < y) return slidingChild;
+ }
+ return null;
+ }
+
+ public View getChildContentView(View v) {
+ return v;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ float densityScale = getResources().getDisplayMetrics().density;
+ mSwipeHelper.setDensityScale(densityScale);
+ float pagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+ mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
}
//**
@@ -260,9 +195,10 @@
child.setPivotY(0);
- final float velocity = (mSlidingChild == child)
- ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN)
- : SWIPE_ESCAPE_VELOCITY;
+ //final float velocity = (mSlidingChild == child)
+ // ? Math.min(mLiftoffVelocity, SWIPE_ANIM_VELOCITY_MIN)
+ // : SWIPE_ESCAPE_VELOCITY;
+ final float velocity = 0f;
final TimeAnimator zoom = new TimeAnimator();
zoom.setTimeListener(new TimeAnimator.TimeListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 9093b3e..449ea99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -50,19 +50,6 @@
static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH;
- static final int[][] DATA_SIGNAL_STRENGTH_ACTIVE = {
- { R.drawable.stat_sys_signal_0,
- R.drawable.stat_sys_signal_1_flowing,
- R.drawable.stat_sys_signal_2_flowing,
- R.drawable.stat_sys_signal_3_flowing,
- R.drawable.stat_sys_signal_4_flowing },
- { R.drawable.stat_sys_signal_0_fully,
- R.drawable.stat_sys_signal_1_fully_flowing,
- R.drawable.stat_sys_signal_2_fully_flowing,
- R.drawable.stat_sys_signal_3_fully_flowing,
- R.drawable.stat_sys_signal_4_fully_flowing }
- };
-
//***** Data connection icons
//GSM/UMTS
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
index 7f4c918..3e9a9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
@@ -25,7 +25,7 @@
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Slog;
-import android.view.View;
+import android.view.Display;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
@@ -41,6 +41,7 @@
ArrayList<OnBarHeightChangedListener> mListeners = new ArrayList<OnBarHeightChangedListener>();
WindowManager mWindowManager;
int mHeight;
+ boolean mPlugged;
public HeightReceiver(Context context) {
mContext = context;
@@ -71,15 +72,24 @@
}
private void setPlugged(boolean plugged) {
+ mPlugged = plugged;
+ updateHeight();
+ }
+
+ public void updateHeight() {
final Resources res = mContext.getResources();
int height = -1;
- if (plugged) {
+ if (mPlugged) {
final DisplayMetrics metrics = new DisplayMetrics();
- mWindowManager.getDefaultDisplay().getRealMetrics(metrics);
- //Slog.i(TAG, "setPlugged: display metrics=" + metrics);
+ Display display = mWindowManager.getDefaultDisplay();
+ display.getRealMetrics(metrics);
+
+ //Slog.i(TAG, "updateHeight: display metrics=" + metrics);
final int shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
- height = shortSide - 720;
+ final int externalShortSide = Math.min(display.getRawExternalWidth(),
+ display.getRawExternalHeight());
+ height = shortSide - externalShortSide;
}
final int minHeight
@@ -87,7 +97,7 @@
if (height < minHeight) {
height = minHeight;
}
- Slog.i(TAG, "Resizing status bar plugged=" + plugged + " height="
+ Slog.i(TAG, "Resizing status bar plugged=" + mPlugged + " height="
+ height + " old=" + mHeight);
mHeight = height;
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 13846ed..96f6e2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -34,6 +34,7 @@
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.LayerDrawable;
import android.provider.Settings;
@@ -188,14 +189,33 @@
mNotificationPanel.setOnTouchListener(
new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
- // the battery and network icons
+ // the battery icon
mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
mBatteryController.addLabelView(
(TextView)mNotificationPanel.findViewById(R.id.battery_text));
+
+ // Bt
mBluetoothController.addIconView(
(ImageView)mNotificationPanel.findViewById(R.id.bluetooth));
- mNetworkController.addCombinedSignalIconView(
- (ImageView)mNotificationPanel.findViewById(R.id.network_signal));
+
+ // network icons: either a combo icon that switches between mobile and data, or distinct
+ // mobile and data icons
+ final ImageView comboRSSI =
+ (ImageView)mNotificationPanel.findViewById(R.id.network_signal);
+ if (comboRSSI != null) {
+ mNetworkController.addCombinedSignalIconView(comboRSSI);
+ }
+ final ImageView mobileRSSI =
+ (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal);
+ if (mobileRSSI != null) {
+ mNetworkController.addPhoneSignalIconView(mobileRSSI);
+ }
+ final ImageView wifiRSSI =
+ (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal);
+ if (wifiRSSI != null) {
+ mNetworkController.addWifiIconView(wifiRSSI);
+ }
+
mNetworkController.addDataTypeIconView(
(ImageView)mNotificationPanel.findViewById(R.id.network_type));
mNetworkController.addDataDirectionOverlayIconView(
@@ -341,8 +361,9 @@
private int getNotificationPanelHeight() {
final Resources res = mContext.getResources();
final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
- return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height),
- d.getRealHeight());
+ final Point size = new Point();
+ d.getRealSize(size);
+ return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
}
@Override
@@ -352,6 +373,7 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
+ mHeightReceiver.updateHeight(); // display size may have changed
loadDimens();
mNotificationPanelParams.height = getNotificationPanelHeight();
WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
@@ -444,9 +466,23 @@
mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
mBluetoothController = new BluetoothController(mContext);
mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth));
+
mNetworkController = new NetworkController(mContext);
- mNetworkController.addCombinedSignalIconView(
- (ImageView)sb.findViewById(R.id.network_signal));
+ final ImageView comboRSSI =
+ (ImageView)sb.findViewById(R.id.network_signal);
+ if (comboRSSI != null) {
+ mNetworkController.addCombinedSignalIconView(comboRSSI);
+ }
+ final ImageView mobileRSSI =
+ (ImageView)sb.findViewById(R.id.mobile_signal);
+ if (mobileRSSI != null) {
+ mNetworkController.addPhoneSignalIconView(mobileRSSI);
+ }
+ final ImageView wifiRSSI =
+ (ImageView)sb.findViewById(R.id.wifi_signal);
+ if (wifiRSSI != null) {
+ mNetworkController.addWifiIconView(wifiRSSI);
+ }
mNetworkController.addDataTypeIconView(
(ImageView)sb.findViewById(R.id.network_type));
mNetworkController.addDataDirectionOverlayIconView(
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 8554b77..bd5f739 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -2,7 +2,8 @@
package="com.android.vpndialogs"
android:sharedUserId="android.uid.system">
- <application android:label="VpnDialogs">
+ <application android:label="VpnDialogs"
+ android:allowBackup="false" >
<activity android:name=".ConfirmDialog"
android:permission="android.permission.VPN"
android:theme="@style/transparent">
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
index de4ea75..044cf4a 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -52,10 +52,9 @@
* account's login/password to unlock the phone (and reset their lock pattern).
*/
public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
- KeyguardUpdateMonitor.InfoCallback,View.OnClickListener, TextWatcher {
+ View.OnClickListener, TextWatcher {
private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
- private static final String LOCK_PATTERN_CLASS =
- "com.android.settings.ChooseLockPattern";
+ private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockPattern";
/**
* The amount of millis to stay awake once this screen detects activity
@@ -71,19 +70,19 @@
private EditText mLogin;
private EditText mPassword;
private Button mOk;
- private Button mEmergencyCall;
/**
* Shown while making asynchronous check of password.
*/
private ProgressDialog mCheckingDialog;
+ private KeyguardStatusViewManager mKeyguardStatusViewManager;
/**
* AccountUnlockScreen constructor.
* @param configuration
* @param updateMonitor
*/
- public AccountUnlockScreen(Context context,Configuration configuration,
+ public AccountUnlockScreen(Context context, Configuration configuration,
KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
LockPatternUtils lockPatternUtils) {
super(context);
@@ -110,12 +109,10 @@
mOk = (Button) findViewById(R.id.ok);
mOk.setOnClickListener(this);
- mEmergencyCall = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyCall.setOnClickListener(this);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
-
mUpdateMonitor = updateMonitor;
- mUpdateMonitor.registerInfoCallback(this);
+
+ mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+ lockPatternUtils, callback);
}
public void afterTextChanged(Editable s) {
@@ -142,7 +139,7 @@
/** {@inheritDoc} */
public void onPause() {
-
+ mKeyguardStatusViewManager.onPause();
}
/** {@inheritDoc} */
@@ -151,7 +148,7 @@
mLogin.setText("");
mPassword.setText("");
mLogin.requestFocus();
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
+ mKeyguardStatusViewManager.onResume();
}
/** {@inheritDoc} */
@@ -171,10 +168,6 @@
if (v == mOk) {
asyncCheckPassword();
}
-
- if (v == mEmergencyCall) {
- mCallback.takeEmergencyCallAction();
- }
}
private void postOnCheckPasswordResult(final boolean success) {
@@ -327,24 +320,4 @@
}
return mCheckingDialog;
}
-
- public void onPhoneStateChanged(String newState) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
- }
-
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
-
- }
-
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-
- }
-
- public void onRingerModeChanged(int state) {
-
- }
-
- public void onTimeChanged() {
-
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
new file mode 100644
index 0000000..7a14480
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -0,0 +1,630 @@
+/*
+ * 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.internal.policy.impl;
+
+import com.android.internal.R;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccCard.State;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+import libcore.util.MutableInt;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/***
+ * Manages a number of views inside of LockScreen layouts. See below for a list of widgets
+ *
+ */
+class KeyguardStatusViewManager implements OnClickListener {
+ private static final boolean DEBUG = true;
+ private static final String TAG = "KeyguardStatusView";
+
+ public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
+ public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
+ public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
+ public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
+ private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
+
+ private static final int SHOW_WIDGET = 8;
+ private static final int HIDE_WIDGET = 9;
+ private static final int INSTRUCTION_TEXT = 10;
+ private static final int CARRIER_TEXT = 11;
+ private static final int CARRIER_HELP_TEXT = 12;
+ private static final int HELP_MESSAGE_TEXT = 13;
+ private static final int OWNER_INFO = 14;
+
+ private StatusMode mStatus;
+ private String mDateFormatString;
+ private TransientTextManager mTransientTextManager;
+
+ // Views that this class controls.
+ // NOTE: These may be null in some LockScreen screens and should protect from NPE
+ private TextView mCarrierView;
+ private TextView mDateView;
+ private TextView mStatus1View;
+ private TextView mOwnerInfoView;
+ private TextView mAlarmStatusView;
+ private View mTransportView;
+
+ // Top-level container view for above views
+ private View mContainer;
+
+ // are we showing battery information?
+ private boolean mShowingBatteryInfo = false;
+
+ // last known plugged in state
+ private boolean mPluggedIn = false;
+
+ // last known battery level
+ private int mBatteryLevel = 100;
+
+ private LockPatternUtils mLockPatternUtils;
+ private KeyguardUpdateMonitor mUpdateMonitor;
+ private Button mEmergencyCallButton;
+ private boolean mShouldEnableUnlock;
+
+ // Shadowed text values
+ private CharSequence mCarrierText;
+ private CharSequence mCarrierHelpText;
+ private String mHelpMessageText;
+ private String mInstructionText;
+ private CharSequence mOwnerInfoText;
+ private boolean mShowingStatus;
+ private KeyguardScreenCallback mCallback;
+ private boolean mHideEmergencyCallButton = false;
+
+ private class TransientTextManager {
+ private TextView mTextView;
+ private class Data {
+ final int icon;
+ final CharSequence text;
+ Data(CharSequence t, int i) {
+ text = t;
+ icon = i;
+ }
+ };
+ private ArrayList<Data> mMessages = new ArrayList<Data>(5);
+
+ TransientTextManager(TextView textView) {
+ mTextView = textView;
+ }
+
+ /* Show given message with icon for up to duration ms. Newer messages override older ones.
+ * The most recent message with the longest duration is shown as messages expire until
+ * nothing is left, in which case the text/icon is defined by a call to
+ * getAltTextMessage() */
+ void post(final CharSequence message, final int icon, long duration) {
+ if (mTextView == null) {
+ return;
+ }
+ mTextView.setText(message);
+ mTextView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
+ final Data data = new Data(message, icon);
+ mContainer.postDelayed(new Runnable() {
+ public void run() {
+ mMessages.remove(data);
+ int last = mMessages.size() - 1;
+ final CharSequence lastText;
+ final int lastIcon;
+ if (last > 0) {
+ final Data oldData = mMessages.get(last);
+ lastText = oldData.text;
+ lastIcon = oldData.icon;
+ } else {
+ final MutableInt tmpIcon = new MutableInt(0);
+ lastText = getAltTextMessage(tmpIcon);
+ lastIcon = tmpIcon.value;
+ }
+ mTextView.setText(lastText);
+ mTextView.setCompoundDrawablesWithIntrinsicBounds(lastIcon, 0, 0, 0);
+ }
+ }, duration);
+ }
+ };
+
+ public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
+ LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback) {
+ mContainer = view;
+ mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
+ mLockPatternUtils = lockPatternUtils;
+ mUpdateMonitor = updateMonitor;
+ mCallback = callback;
+
+ mCarrierView = (TextView) findViewById(R.id.carrier);
+ mDateView = (TextView) findViewById(R.id.date);
+ mStatus1View = (TextView) findViewById(R.id.status1);
+ mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
+ mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
+ mTransportView = findViewById(R.id.transport);
+ mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
+ if (mEmergencyCallButton != null) {
+ mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
+ mEmergencyCallButton.setOnClickListener(this);
+ mEmergencyCallButton.setFocusable(false); // touch only!
+ }
+
+ mTransientTextManager = new TransientTextManager(mCarrierView);
+
+ updateEmergencyCallButtonState();
+
+ resetStatusInfo();
+ refreshDate();
+ updateOwnerInfo();
+
+ // Required to get Marquee to work.
+ final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,
+ mAlarmStatusView };
+ for (View v : scrollableViews) {
+ if (v != null) {
+ v.setSelected(true);
+ }
+ }
+
+ // until we get an update...
+ setCarrierText(LockPatternUtils.getCarrierString(
+ mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
+ }
+
+ public void enterWidgetMode() {
+ if (mTransportView != null) {
+ mTransportView.setVisibility(View.VISIBLE);
+ update(SHOW_WIDGET, null);
+ }
+ }
+
+ public void leaveWidgetMode() {
+ if (mTransportView != null) {
+ mTransportView.setVisibility(View.GONE);
+ update(HIDE_WIDGET, null);
+ }
+ }
+
+ private boolean inWidgetMode() {
+ return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
+ }
+
+ void setInstructionText(String string) {
+ mInstructionText = string;
+ update(INSTRUCTION_TEXT, string);
+ }
+
+ void setCarrierText(CharSequence string) {
+ mCarrierText = string;
+ update(CARRIER_TEXT, string);
+ }
+
+ void setOwnerInfo(CharSequence string) {
+ mOwnerInfoText = string;
+ update(OWNER_INFO, string);
+ }
+
+ /**
+ * Sets the carrier help text message, if view is present. Carrier help text messages are
+ * typically for help dealing with SIMS and connectivity.
+ *
+ * @param resId resource id of the message
+ */
+ public void setCarrierHelpText(int resId) {
+ mCarrierHelpText = getContext().getText(resId);
+ update(CARRIER_HELP_TEXT, mCarrierHelpText);
+ }
+
+ /**
+ * Unlock help message. This is typically for help with unlock widgets, e.g. "wrong password"
+ * or "try again."
+ *
+ * @param textResId
+ * @param lockIcon
+ */
+ public void setHelpMessage(int textResId, int lockIcon) {
+ mHelpMessageText = getContext().getString(textResId);
+ update(HELP_MESSAGE_TEXT, mHelpMessageText);
+ }
+
+ private void update(int what, CharSequence string) {
+ if (inWidgetMode()) {
+ if (DEBUG) Log.v(TAG, "inWidgetMode() is true");
+ // Use Transient text for messages shown while widget is shown.
+ switch (what) {
+ case INSTRUCTION_TEXT:
+ case CARRIER_HELP_TEXT:
+ case HELP_MESSAGE_TEXT:
+ mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
+ break;
+
+ case OWNER_INFO:
+ case CARRIER_TEXT:
+ default:
+ Log.w(TAG, "Not showing message id " + what + ", str=" + string);
+ }
+ } else {
+ updateStatusLines(mShowingStatus);
+ }
+ }
+
+ public void onPause() {
+ mUpdateMonitor.removeCallback(mInfoCallback);
+ mUpdateMonitor.removeCallback(mSimStateCallback);
+ }
+
+ /** {@inheritDoc} */
+ public void onResume() {
+ mUpdateMonitor.registerInfoCallback(mInfoCallback);
+ mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+ updateEmergencyCallButtonState();
+ resetStatusInfo();
+ }
+
+ void resetStatusInfo() {
+ mInstructionText = null;
+ mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
+ mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
+ mBatteryLevel = mUpdateMonitor.getBatteryLevel();
+ updateStatusLines(true);
+ }
+
+ /**
+ * Update the status lines based on these rules:
+ * AlarmStatus: Alarm state always gets it's own line.
+ * Status1 is shared between help, battery status and generic unlock instructions,
+ * prioritized in that order.
+ * @param showStatusLines status lines are shown if true
+ */
+ void updateStatusLines(boolean showStatusLines) {
+ if (DEBUG) Log.v(TAG, "updateStatusLines(" + showStatusLines + ")");
+ mShowingStatus = showStatusLines;
+ updateAlarmInfo();
+ updateOwnerInfo();
+ updateStatus1();
+ updateCarrierText();
+ }
+
+ private void updateAlarmInfo() {
+ if (mAlarmStatusView != null) {
+ String nextAlarm = mLockPatternUtils.getNextAlarm();
+ boolean showAlarm = mShowingStatus && !TextUtils.isEmpty(nextAlarm);
+ mAlarmStatusView.setText(nextAlarm);
+ mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
+ mAlarmStatusView.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void updateOwnerInfo() {
+ final ContentResolver res = getContext().getContentResolver();
+ final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
+ Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
+ mOwnerInfoText = ownerInfoEnabled ?
+ Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO) : null;
+ if (mOwnerInfoView != null) {
+ mOwnerInfoView.setText(mOwnerInfoText);
+ mOwnerInfoView.setVisibility(TextUtils.isEmpty(mOwnerInfoText) ? View.GONE:View.VISIBLE);
+ }
+ }
+
+ private void updateStatus1() {
+ if (mStatus1View != null) {
+ MutableInt icon = new MutableInt(0);
+ CharSequence string = getPriorityTextMessage(icon);
+ mStatus1View.setText(string);
+ mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
+ mStatus1View.setVisibility(mShowingStatus ? View.VISIBLE : View.INVISIBLE);
+ }
+ }
+
+ private void updateCarrierText() {
+ if (!inWidgetMode() && mCarrierView != null) {
+ mCarrierView.setText(mCarrierText);
+ }
+ }
+
+ private CharSequence getAltTextMessage(MutableInt icon) {
+ // If we have replaced the status area with a single widget, then this code
+ // prioritizes what to show in that space when all transient messages are gone.
+ CharSequence string = null;
+ if (mShowingBatteryInfo) {
+ // Battery status
+ if (mPluggedIn) {
+ // Charging or charged
+ if (mUpdateMonitor.isDeviceCharged()) {
+ string = getContext().getString(R.string.lockscreen_charged);
+ } else {
+ string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
+ }
+ icon.value = CHARGING_ICON;
+ } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+ // Battery is low
+ string = getContext().getString(R.string.lockscreen_low_battery);
+ icon.value = BATTERY_LOW_ICON;
+ }
+ } else {
+ string = mCarrierText;
+ }
+ return string;
+ }
+
+ private CharSequence getPriorityTextMessage(MutableInt icon) {
+ CharSequence string = null;
+ if (!TextUtils.isEmpty(mInstructionText)) {
+ // Instructions only
+ string = mInstructionText;
+ icon.value = LOCK_ICON;
+ } else if (mShowingBatteryInfo) {
+ // Battery status
+ if (mPluggedIn) {
+ // Charging or charged
+ if (mUpdateMonitor.isDeviceCharged()) {
+ string = getContext().getString(R.string.lockscreen_charged);
+ } else {
+ string = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
+ }
+ icon.value = CHARGING_ICON;
+ } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
+ // Battery is low
+ string = getContext().getString(R.string.lockscreen_low_battery);
+ icon.value = BATTERY_LOW_ICON;
+ }
+ } else if (!inWidgetMode() && mOwnerInfoView == null && mOwnerInfoText != null) {
+ // OwnerInfo shows in status if we don't have a dedicated widget
+ string = mOwnerInfoText;
+ }
+ return string;
+ }
+
+ void refreshDate() {
+ if (mDateView != null) {
+ mDateView.setText(DateFormat.format(mDateFormatString, new Date()));
+ }
+ }
+
+ boolean shouldEnableUnlock() {
+ return mShouldEnableUnlock;
+ }
+
+ /**
+ * Determine the current status of the lock screen given the sim state and other stuff.
+ */
+ public StatusMode getStatusForIccState(IccCard.State simState) {
+ boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
+ && (simState == IccCard.State.ABSENT || simState == IccCard.State.PERM_DISABLED));
+
+ // Assume we're NETWORK_LOCKED if not provisioned
+ simState = missingAndNotProvisioned ? State.NETWORK_LOCKED : simState;
+ switch (simState) {
+ case ABSENT:
+ return StatusMode.SimMissing;
+ case NETWORK_LOCKED:
+ return StatusMode.SimMissingLocked;
+ case NOT_READY:
+ return StatusMode.SimMissing;
+ case PIN_REQUIRED:
+ return StatusMode.SimLocked;
+ case PUK_REQUIRED:
+ return StatusMode.SimPukLocked;
+ case READY:
+ return StatusMode.Normal;
+ case PERM_DISABLED:
+ return StatusMode.SimPermDisabled;
+ case UNKNOWN:
+ return StatusMode.SimMissing;
+ }
+ return StatusMode.SimMissing;
+ }
+
+ private Context getContext() {
+ return mContainer.getContext();
+ }
+
+ /**
+ * Update carrier text, carrier help and emergency button to match the current status based
+ * on SIM state.
+ *
+ * @param simState
+ */
+ private void updateWithSimStatus(State simState) {
+ // The emergency call button no longer appears on this screen.
+ if (DEBUG) Log.d(TAG, "updateLayout: status=" + mStatus);
+
+ CharSequence carrierText = null;
+ int carrierHelpTextId = 0;
+ mShouldEnableUnlock = true;
+ mStatus = getStatusForIccState(simState);
+
+ switch (mStatus) {
+ case Normal:
+ carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+ mUpdateMonitor.getTelephonySpn());
+ break;
+
+ case NetworkLocked:
+ carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+ getContext().getText(R.string.lockscreen_network_locked_message));
+ carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
+ break;
+
+ case SimMissing:
+ carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short);
+ carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
+ break;
+
+ case SimPermDisabled:
+ carrierText = getContext().getText(R.string.lockscreen_missing_sim_message_short);
+ carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
+ break;
+
+ case SimMissingLocked:
+ carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+ getContext().getText(R.string.lockscreen_missing_sim_message_short));
+ carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
+ mShouldEnableUnlock = false;
+ break;
+
+ case SimLocked:
+ carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+ getContext().getText(R.string.lockscreen_sim_locked_message));
+ break;
+
+ case SimPukLocked:
+ carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+ getContext().getText(R.string.lockscreen_sim_puk_locked_message));
+ if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
+ mShouldEnableUnlock = false;
+ }
+ break;
+ }
+
+ setCarrierText(carrierText);
+ setCarrierHelpText(carrierHelpTextId);
+ updateEmergencyCallButtonState();
+ }
+
+ private View findViewById(int id) {
+ return mContainer.findViewById(id);
+ }
+
+ /**
+ * The status of this lock screen. Primarily used for widgets on LockScreen.
+ */
+ enum StatusMode {
+ /**
+ * Normal case (sim card present, it's not locked)
+ */
+ Normal(true),
+
+ /**
+ * The sim card is 'network locked'.
+ */
+ NetworkLocked(true),
+
+ /**
+ * The sim card is missing.
+ */
+ SimMissing(false),
+
+ /**
+ * The sim card is missing, and this is the device isn't provisioned, so we don't let
+ * them get past the screen.
+ */
+ SimMissingLocked(false),
+
+ /**
+ * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
+ * times.
+ */
+ SimPukLocked(false),
+
+ /**
+ * The sim card is locked.
+ */
+ SimLocked(true),
+
+ /**
+ * The sim card is permanently disabled due to puk unlock failure
+ */
+ SimPermDisabled(false);
+
+ private final boolean mShowStatusLines;
+
+ StatusMode(boolean mShowStatusLines) {
+ this.mShowStatusLines = mShowStatusLines;
+ }
+
+ /**
+ * @return Whether the status lines (battery level and / or next alarm) are shown while
+ * in this state. Mostly dictated by whether this is room for them.
+ */
+ public boolean shouldShowStatusLines() {
+ return mShowStatusLines;
+ }
+ }
+
+ private void updateEmergencyCallButtonState() {
+ if (mEmergencyCallButton != null) {
+ mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ if (mHideEmergencyCallButton) {
+ mEmergencyCallButton.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ private KeyguardUpdateMonitor.InfoCallback mInfoCallback
+ = new KeyguardUpdateMonitor.InfoCallback() {
+
+ public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
+ int batteryLevel) {
+ mShowingBatteryInfo = showBatteryInfo;
+ mPluggedIn = pluggedIn;
+ mBatteryLevel = batteryLevel;
+ updateStatusLines(true);
+ }
+
+ public void onTimeChanged() {
+ refreshDate();
+ }
+
+ public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+ setCarrierText(LockPatternUtils.getCarrierString(plmn, spn));
+ }
+
+ public void onRingerModeChanged(int state) {
+
+ }
+
+ public void onPhoneStateChanged(String newState) {
+ updateEmergencyCallButtonState();
+ }
+
+ public void onTransportControlStateChanged(int state) {
+ // TODO: define what state means
+ if (state == 0) {
+ leaveWidgetMode();
+ } else {
+ enterWidgetMode();
+ }
+ }
+ };
+
+ private SimStateCallback mSimStateCallback = new SimStateCallback() {
+
+ public void onSimStateChanged(State simState) {
+ updateWithSimStatus(simState);
+ }
+ };
+
+ public void onClick(View v) {
+ if (v == mEmergencyCallButton) {
+ mCallback.takeEmergencyCallAction();
+ }
+ }
+
+ public void hideEmergencyCallButton() {
+ mHideEmergencyCallButton = true;
+ }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index f385a23..7faf1a4 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -95,6 +95,7 @@
private static final int MSG_SIM_STATE_CHANGE = 304;
private static final int MSG_RINGER_MODE_CHANGED = 305;
private static final int MSG_PHONE_STATE_CHANGED = 306;
+ private static final int MSG_TRANSPORT_CONTROL_STATE_CHANGED = 307;
/**
@@ -172,6 +173,9 @@
case MSG_PHONE_STATE_CHANGED:
handlePhoneStateChanged((String)msg.obj);
break;
+ case MSG_TRANSPORT_CONTROL_STATE_CHANGED:
+ handleTransportControlStateChanged(msg.arg1);
+ break;
}
}
};
@@ -261,10 +265,23 @@
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
}
+ // TODO
+ else if ("android.media.TRANSPORT_CONTROL_CHANGED".equals(action)) {
+ int state = intent.getIntExtra("state", 0);
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_TRANSPORT_CONTROL_STATE_CHANGED,
+ state));
+ }
}
}, filter);
}
+ protected void handleTransportControlStateChanged(int state) {
+ if (DEBUG) Log.d(TAG, "handleTransportControlStateChanged()");
+ for (int i = 0; i < mInfoCallbacks.size(); i++) {
+ mInfoCallbacks.get(i).onTransportControlStateChanged(state);
+ }
+ }
+
protected void handlePhoneStateChanged(String newState) {
if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
for (int i = 0; i < mInfoCallbacks.size(); i++) {
@@ -449,6 +466,12 @@
* {@link TelephonyManager#EXTRA_STATE_OFFHOOK
*/
void onPhoneStateChanged(String newState);
+
+ /**
+ * Called when AudioService informs us of a change to the transport control client.
+ *
+ */
+ void onTransportControlStateChanged(int state);
}
/**
@@ -467,7 +490,8 @@
if (!mInfoCallbacks.contains(callback)) {
mInfoCallbacks.add(callback);
} else {
- Log.e(TAG, "Object tried to add another INFO callback", new Exception("Whoops"));
+ if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
+ new Exception("Whoops"));
}
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 7983278..e5a7d64 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -61,7 +61,8 @@
* @param callback Used to notify of changes.
*/
public KeyguardViewManager(Context context, ViewManager viewManager,
- KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties, KeyguardUpdateMonitor updateMonitor) {
+ KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
+ KeyguardUpdateMonitor updateMonitor) {
mContext = context;
mViewManager = viewManager;
mCallback = callback;
@@ -116,7 +117,7 @@
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
flags, PixelFormat.TRANSLUCENT);
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
+ lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
lp.setTitle("Keyguard");
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 1c4084c..4a14dd9 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -17,32 +17,24 @@
package com.android.internal.policy.impl;
import com.android.internal.R;
-import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.SlidingTab;
import com.android.internal.widget.WaveView;
-import com.android.internal.widget.WaveView.OnTriggerListener;
import com.android.internal.widget.multiwaveview.MultiWaveView;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.ColorStateList;
-import android.text.format.DateFormat;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
-import android.graphics.drawable.Drawable;
import android.util.Log;
import android.media.AudioManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
import android.provider.Settings;
-import java.util.Date;
import java.io.File;
/**
@@ -50,104 +42,30 @@
* information about the device depending on its state, and how to get
* past it, as applicable.
*/
-class LockScreen extends LinearLayout implements KeyguardScreen,
- KeyguardUpdateMonitor.InfoCallback,
- KeyguardUpdateMonitor.SimStateCallback {
+class LockScreen extends LinearLayout implements KeyguardScreen {
private static final boolean DBG = false;
private static final String TAG = "LockScreen";
private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
-
- private Status mStatus = Status.Normal;
+ private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
+ private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
private LockPatternUtils mLockPatternUtils;
private KeyguardUpdateMonitor mUpdateMonitor;
private KeyguardScreenCallback mCallback;
- private TextView mScreenLocked;
- private TextView mEmergencyCallText;
- private Button mEmergencyCallButton;
-
// current configuration state of keyboard and display
private int mKeyboardHidden;
private int mCreationOrientation;
- // are we showing battery information?
- private boolean mShowingBatteryInfo = false;
-
- // last known plugged in state
- private boolean mPluggedIn = false;
-
- // last known battery level
- private int mBatteryLevel = 100;
-
private boolean mSilentMode;
private AudioManager mAudioManager;
- private String mDateFormatString;
- private java.text.DateFormat mTimeFormat;
private boolean mEnableMenuKeyInLockScreen;
- private StatusView mStatusView;
+ private KeyguardStatusViewManager mStatusViewManager;
private UnlockWidgetCommonMethods mUnlockWidgetMethods;
private View mUnlockWidget;
-
- /**
- * The status of this lock screen.
- */
- enum Status {
- /**
- * Normal case (sim card present, it's not locked)
- */
- Normal(true),
-
- /**
- * The sim card is 'network locked'.
- */
- NetworkLocked(true),
-
- /**
- * The sim card is missing.
- */
- SimMissing(false),
-
- /**
- * The sim card is missing, and this is the device isn't provisioned, so we don't let
- * them get past the screen.
- */
- SimMissingLocked(false),
-
- /**
- * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
- * times.
- */
- SimPukLocked(false),
-
- /**
- * The sim card is locked.
- */
- SimLocked(true),
-
- /**
- * The sim card is permanently disabled due to puk unlock failure
- */
- SimPermDisabled(false);
-
- private final boolean mShowStatusLines;
-
- Status(boolean mShowStatusLines) {
- this.mShowStatusLines = mShowStatusLines;
- }
-
- /**
- * @return Whether the status lines (battery level and / or next alarm) are shown while
- * in this state. Mostly dictated by whether this is room for them.
- */
- public boolean showStatusLines() {
- return mShowStatusLines;
- }
- }
-
private interface UnlockWidgetCommonMethods {
// Update resources based on phone state
public void updateResources();
@@ -191,7 +109,6 @@
mCallback.goToUnlockScreen();
} else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
toggleRingMode();
- doSilenceRingToast();
mCallback.pokeWakelock();
}
}
@@ -223,9 +140,6 @@
}
}
- private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
- private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
-
class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
private final WaveView mWaveView;
@@ -290,7 +204,6 @@
mCallback.goToUnlockScreen();
} else if (target == 2) {
toggleRingMode();
- doSilenceRingToast();
mUnlockWidgetMethods.updateResources();
mCallback.pokeWakelock();
}
@@ -327,27 +240,12 @@
}, WAIT_FOR_ANIMATION_TIMEOUT);
}
- private void doSilenceRingToast() {
- String message = mSilentMode ?
- getContext().getString(R.string.global_action_silent_mode_on_status) :
- getContext().getString(R.string.global_action_silent_mode_off_status);
-
- final int toastIcon = mSilentMode
- ? R.drawable.ic_lock_ringer_off
- : R.drawable.ic_lock_ringer_on;
-
- final int toastColor = mSilentMode
- ? getContext().getResources().getColor(R.color.keyguard_text_color_soundoff)
- : getContext().getResources().getColor(R.color.keyguard_text_color_soundon);
- toastMessage(mScreenLocked, message, toastColor, toastIcon);
- }
-
private void toggleRingMode() {
// toggle silent mode
mSilentMode = !mSilentMode;
if (mSilentMode) {
final boolean vibe = (Settings.System.getInt(
- getContext().getContentResolver(),
+ mContext.getContentResolver(),
Settings.System.VIBRATE_IN_SILENT, 1) == 1);
mAudioManager.setRingerMode(vibe
@@ -409,29 +307,17 @@
inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
}
- mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
+ mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
+ mCallback);
- mScreenLocked = (TextView) findViewById(R.id.screenLocked);
-
- mEmergencyCallText = (TextView) findViewById(R.id.emergencyCallText);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
-
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- mEmergencyCallButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- mCallback.takeEmergencyCallAction();
- }
- });
+ // LockScreen doesn't show the emergency call button by default
+ mStatusViewManager.hideEmergencyCallButton();
setFocusable(true);
setFocusableInTouchMode(true);
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- mUpdateMonitor.registerInfoCallback(this);
- mUpdateMonitor.registerSimStateCallback(this);
-
- mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mSilentMode = isSilentMode();
mUnlockWidget = findViewById(R.id.unlock_widget);
@@ -466,28 +352,12 @@
if (DBG) Log.v(TAG, "*** LockScreen accel is "
+ (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
-
- resetStatusInfo(updateMonitor);
}
private boolean isSilentMode() {
return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
}
- private void resetStatusInfo(KeyguardUpdateMonitor updateMonitor) {
- mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
- mPluggedIn = updateMonitor.isDevicePluggedIn();
- mBatteryLevel = updateMonitor.getBatteryLevel();
-
- mStatus = getCurrentStatus(updateMonitor.getSimState());
- updateLayout(mStatus);
-
- mTimeFormat = DateFormat.getTimeFormat(getContext());
- mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
- refreshTimeAndDateDisplay();
- updateStatusLines();
- }
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) {
@@ -496,263 +366,6 @@
return false;
}
- /**
- * Displays a message in a text view and then restores the previous text.
- * @param textView The text view.
- * @param text The text.
- * @param color The color to apply to the text, or 0 if the existing color should be used.
- * @param iconResourceId The left hand icon.
- */
- private void toastMessage(final TextView textView, final String text, final int color, final int iconResourceId) {
- if (mPendingR1 != null) {
- textView.removeCallbacks(mPendingR1);
- mPendingR1 = null;
- }
- if (mPendingR2 != null) {
- mPendingR2.run(); // fire immediately, restoring non-toasted appearance
- textView.removeCallbacks(mPendingR2);
- mPendingR2 = null;
- }
-
- final String oldText = textView.getText().toString();
- final ColorStateList oldColors = textView.getTextColors();
-
- mPendingR1 = new Runnable() {
- public void run() {
- textView.setText(text);
- if (color != 0) {
- textView.setTextColor(color);
- }
- textView.setCompoundDrawablesWithIntrinsicBounds(iconResourceId, 0, 0, 0);
- }
- };
-
- textView.postDelayed(mPendingR1, 0);
- mPendingR2 = new Runnable() {
- public void run() {
- textView.setText(oldText);
- textView.setTextColor(oldColors);
- textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
- }
- };
- textView.postDelayed(mPendingR2, 3500);
- }
- private Runnable mPendingR1;
- private Runnable mPendingR2;
-
- /** {@inheritDoc} */
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
- int batteryLevel) {
- if (DBG) Log.d(TAG, "onRefreshBatteryInfo(" + showBatteryInfo + ", " + pluggedIn + ")");
-
- mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel);
-
- mShowingBatteryInfo = showBatteryInfo;
- mPluggedIn = pluggedIn;
- mBatteryLevel = batteryLevel;
-
- updateStatusLines();
- }
-
- /** {@inheritDoc} */
- public void onTimeChanged() {
- refreshTimeAndDateDisplay();
- }
-
- private void refreshTimeAndDateDisplay() {
- mStatusView.refreshTimeAndDateDisplay();
- }
-
- private void updateStatusLines() {
- mStatusView.updateStatusLines(mStatus.showStatusLines());
- }
-
- /** {@inheritDoc} */
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- if (DBG) Log.d(TAG, "onRefreshCarrierInfo(" + plmn + ", " + spn + ")");
- updateLayout(mStatus);
- }
-
- /**
- * Determine the current status of the lock screen given the sim state and other stuff.
- */
- private Status getCurrentStatus(IccCard.State simState) {
- boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
- && (simState == IccCard.State.ABSENT
- || simState == IccCard.State.PERM_DISABLED));
-
- if (missingAndNotProvisioned) {
- return Status.SimMissingLocked;
- }
-
- switch (simState) {
- case ABSENT:
- return Status.SimMissing;
- case NETWORK_LOCKED:
- return Status.SimMissingLocked;
- case NOT_READY:
- return Status.SimMissing;
- case PIN_REQUIRED:
- return Status.SimLocked;
- case PUK_REQUIRED:
- return Status.SimPukLocked;
- case READY:
- return Status.Normal;
- case PERM_DISABLED:
- return Status.SimPermDisabled;
- case UNKNOWN:
- return Status.SimMissing;
- }
- return Status.SimMissing;
- }
-
- /**
- * Enables unlocking of this screen. Typically just shows the unlock widget.
- */
- private void enableUnlock() {
- mUnlockWidgetMethods.getView().setVisibility(View.VISIBLE);
- }
-
- /**
- * Disable unlocking of this screen. Typically just hides the unlock widget.
- */
- private void disableUnlock() {
- mUnlockWidgetMethods.getView().setVisibility(View.GONE);
- }
-
- /**
- * Update the layout to match the current status.
- */
- private void updateLayout(Status status) {
- // The emergency call button no longer appears on this screen.
- if (DBG) Log.d(TAG, "updateLayout: status=" + status);
-
- mEmergencyCallButton.setVisibility(View.GONE); // in almost all cases
-
- switch (status) {
- case Normal:
- // text
- mStatusView.setCarrierText(
- getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- mUpdateMonitor.getTelephonySpn()));
-
- // Empty now, but used for sliding tab feedback
- mScreenLocked.setText("");
-
- // layout
- mScreenLocked.setVisibility(View.INVISIBLE);
- mEmergencyCallText.setVisibility(View.GONE);
- enableUnlock();
- break;
-
- case NetworkLocked:
- // The carrier string shows both sim card status (i.e. No Sim Card) and
- // carrier's name and/or "Emergency Calls Only" status
- mStatusView.setCarrierText(
- getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- getContext().getText(R.string.lockscreen_network_locked_message)));
- mScreenLocked.setText(R.string.lockscreen_instructions_when_pattern_disabled);
-
- // layout
- mScreenLocked.setVisibility(View.VISIBLE);
- mEmergencyCallText.setVisibility(View.GONE);
- enableUnlock();
- break;
-
- case SimMissing:
- // text
- mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
- mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions_long);
-
- // layout
- mScreenLocked.setVisibility(View.VISIBLE);
- mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
- enableUnlock(); // do not need to show the e-call button; user may unlock
- break;
-
- case SimPermDisabled:
- // text
- mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
- mScreenLocked.setText(
- R.string.lockscreen_permanent_disabled_sim_instructions);
-
- // layout
- mScreenLocked.setVisibility(View.VISIBLE);
- mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
- enableUnlock(); // do not need to show the e-call button; user may unlock
- break;
-
- case SimMissingLocked:
- // text
- mStatusView.setCarrierText(
- getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- getContext().getText(R.string.lockscreen_missing_sim_message_short)));
- mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions);
-
- // layout
- mScreenLocked.setVisibility(View.VISIBLE);
- mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- disableUnlock();
- break;
-
- case SimLocked:
- // text
- mStatusView.setCarrierText(
- getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- getContext().getText(R.string.lockscreen_sim_locked_message)));
-
- // layout
- mScreenLocked.setVisibility(View.INVISIBLE);
- mEmergencyCallText.setVisibility(View.GONE);
- enableUnlock();
- break;
-
- case SimPukLocked:
- // text
- mStatusView.setCarrierText(
- getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- getContext().getText(R.string.lockscreen_sim_puk_locked_message)));
- mScreenLocked.setText(R.string.lockscreen_sim_puk_locked_instructions);
-
- // layout
- mLockPatternUtils.updateEmergencyCallText(mEmergencyCallText);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- if (mLockPatternUtils.isPukUnlockScreenEnable()) {
- mScreenLocked.setVisibility(View.INVISIBLE);
- enableUnlock();
- } else {
- mScreenLocked.setVisibility(View.VISIBLE);
- disableUnlock();
- }
- break;
- }
- }
-
- static CharSequence getCarrierString(CharSequence telephonyPlmn, CharSequence telephonySpn) {
- if (telephonyPlmn != null && telephonySpn == null) {
- return telephonyPlmn;
- } else if (telephonyPlmn != null && telephonySpn != null) {
- return telephonyPlmn + "|" + telephonySpn;
- } else if (telephonyPlmn == null && telephonySpn != null) {
- return telephonySpn;
- } else {
- return "";
- }
- }
-
- public void onSimStateChanged(IccCard.State simState) {
- if (DBG) Log.d(TAG, "onSimStateChanged(" + simState + ")");
- mStatus = getCurrentStatus(simState);
- updateLayout(mStatus);
- updateStatusLines();
- }
-
void updateConfiguration() {
Configuration newConfig = getResources().getConfiguration();
if (newConfig.orientation != mCreationOrientation) {
@@ -796,12 +409,13 @@
/** {@inheritDoc} */
public void onPause() {
+ mStatusViewManager.onPause();
mUnlockWidgetMethods.reset(false);
}
/** {@inheritDoc} */
public void onResume() {
- resetStatusInfo(mUpdateMonitor);
+ mStatusViewManager.onResume();
mUnlockWidgetMethods.ping();
}
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index e177565..7c1f93a 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -21,7 +21,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
-import com.android.internal.policy.impl.PatternUnlockScreen.FooterMode;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardView;
@@ -38,6 +37,7 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
@@ -53,7 +53,7 @@
* an unlock password
*/
public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen,
- View.OnClickListener, KeyguardUpdateMonitor.InfoCallback, OnEditorActionListener {
+ OnEditorActionListener {
private static final String TAG = "PasswordUnlockScreen";
private final KeyguardUpdateMonitor mUpdateMonitor;
@@ -62,19 +62,16 @@
private boolean mIsAlpha;
private EditText mPasswordEntry;
- private Button mEmergencyCallButton;
private LockPatternUtils mLockPatternUtils;
private PasswordEntryKeyboardView mKeyboardView;
- private PasswordEntryKeyboardView mKeyboardViewAlpha;
private PasswordEntryKeyboardHelper mKeyboardHelper;
- private PasswordEntryKeyboardHelper mKeyboardHelperAlpha;
private int mCreationOrientation;
private int mCreationHardKeyboardHidden;
private CountDownTimer mCountdownTimer;
- private StatusView mStatusView;
- private final boolean mUseSystemIME = true; // TODO: Make configurable
+ private KeyguardStatusViewManager mStatusViewManager;
+ private boolean mUseSystemIME = true; // TODO: Make configurable
private boolean mResuming; // used to prevent poking the wakelock during onResume()
// To avoid accidental lockout due to events while the device in in the pocket, ignore
@@ -99,48 +96,28 @@
layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
}
- mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
+ mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
+ mCallback);
final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
|| DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
|| DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
- // TODO: re-enable on phones with keyboards
- final boolean isPhysicalKbShowing = false;
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
- mKeyboardViewAlpha = (PasswordEntryKeyboardView) findViewById(R.id.keyboardAlpha);
mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- if (mIsAlpha && !isPhysicalKbShowing && !mUseSystemIME) {
- // Toggle visibility of alpha keyboard
- final boolean visible = mKeyboardViewAlpha.getVisibility() == View.VISIBLE;
- mKeyboardViewAlpha.setVisibility(visible ? View.GONE : View.VISIBLE);
- }
- mCallback.pokeWakelock();
- }
- });
-
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyCallButton.setOnClickListener(this);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
- //mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
- if (mKeyboardViewAlpha == null || !mIsAlpha) {
- mKeyboardHelper.setKeyboardMode(mIsAlpha ?
- PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
- : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
- mKeyboardView.setVisibility(isPhysicalKbShowing ? View.INVISIBLE : View.VISIBLE);
- } else {
- mKeyboardHelperAlpha = new PasswordEntryKeyboardHelper(context, mKeyboardViewAlpha,
- this, false);
- mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
- mKeyboardHelperAlpha.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
+ if (mIsAlpha) {
+ // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
+ mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
mKeyboardView.setVisibility(View.GONE);
- mPasswordEntry.setWidth(mKeyboardViewAlpha.getLayoutParams().width);
+ } else {
+ // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
+ mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+ mKeyboardView.setVisibility(mCreationHardKeyboardHidden
+ == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
}
mPasswordEntry.requestFocus();
@@ -150,34 +127,25 @@
mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_PASSWORD);
- // mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
- // StatusView.LOCK_ICON);
+ //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code,
+ //KeyguardStatusViewManager.LOCK_ICON);
} else {
mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
| InputType.TYPE_NUMBER_VARIATION_PASSWORD);
- //mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
- // StatusView.LOCK_ICON);
+ //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code,
+ //KeyguardStatusViewManager.LOCK_ICON);
}
mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
com.android.internal.R.array.config_virtualKeyVibePattern : 0);
- if (mKeyboardHelperAlpha != null) {
- mKeyboardHelperAlpha.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
- com.android.internal.R.array.config_virtualKeyVibePattern : 0);
- }
- // until we get an update...
- mStatusView.setCarrierText(LockScreen.getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- mUpdateMonitor.getTelephonySpn()));
-
- mUpdateMonitor.registerInfoCallback(this);
- //mUpdateMonitor.registerSimStateCallback(this);
-
- resetStatusInfo();
-
- // Poke the wakelock any time the text is modified
+ // Poke the wakelock any time the text is selected or modified
+ mPasswordEntry.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mCallback.pokeWakelock();
+ }
+ });
mPasswordEntry.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@@ -206,20 +174,18 @@
/** {@inheritDoc} */
public void onPause() {
-
+ mStatusViewManager.onPause();
}
/** {@inheritDoc} */
public void onResume() {
mResuming = true;
// reset status
- mStatusView.resetStatusInfo(mUpdateMonitor, mLockPatternUtils);
+ mStatusViewManager.onResume();
// start fresh
mPasswordEntry.setText("");
- resetStatusInfo();
mPasswordEntry.requestFocus();
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
// if the user is currently locked out, enforce it.
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
@@ -234,19 +200,12 @@
mUpdateMonitor.removeCallback(this);
}
- public void onClick(View v) {
- if (v == mEmergencyCallButton) {
- mCallback.takeEmergencyCallAction();
- }
- mCallback.pokeWakelock();
- }
-
private void verifyPasswordAndUnlock() {
String entry = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(entry)) {
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
- mStatusView.setInstructionText(null);
+ mStatusViewManager.setInstructionText(null);
KeyStore.getInstance().password(entry);
} else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
// to avoid accidental lockout, only count attempts that are long enough to be a
@@ -257,9 +216,11 @@
long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
handleAttemptLockout(deadline);
}
- mStatusView.setInstructionText(R.string.lockscreen_password_wrong);
+ mStatusViewManager.setInstructionText(
+ mContext.getString(R.string.lockscreen_password_wrong));
} else if (entry.length() > 0) {
- mStatusView.setInstructionText(R.string.lockscreen_password_wrong);
+ mStatusViewManager.setInstructionText(
+ mContext.getString(R.string.lockscreen_password_wrong));
}
mPasswordEntry.setText("");
}
@@ -277,19 +238,19 @@
String instructions = getContext().getString(
R.string.lockscreen_too_many_failed_attempts_countdown,
secondsRemaining);
- mStatusView.setInstructionText(instructions);
+ mStatusViewManager.setInstructionText(instructions);
}
@Override
public void onFinish() {
mPasswordEntry.setEnabled(true);
mKeyboardView.setEnabled(true);
- resetStatusInfo();
+ mStatusViewManager.resetStatusInfo();
+ mCountdownTimer = null;
}
}.start();
}
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
mCallback.pokeWakelock();
@@ -329,39 +290,4 @@
}
return false;
}
-
- // ---------- InfoCallback
-
- /** {@inheritDoc} */
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
- mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel);
- }
-
- /** {@inheritDoc} */
- public void onTimeChanged() {
- mStatusView.onTimeChanged();
- }
-
- /** {@inheritDoc} */
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- mStatusView.onRefreshCarrierInfo(plmn, spn);
- }
-
- /** {@inheritDoc} */
- public void onRingerModeChanged(int state) {
- // not currently used
- }
-
- // ---------- SimStateCallback
-
- /** {@inheritDoc} */
- public void onPhoneStateChanged(String newState) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- }
-
- private void resetStatusInfo() {
- mStatusView.setInstructionText(null);
- mStatusView.updateStatusLines(true);
- }
-
}
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 6573286..a3db1c3 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -23,13 +23,10 @@
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;
import android.util.Log;
import com.android.internal.R;
-import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
@@ -42,8 +39,7 @@
* the user how to unlock their device, or make an emergency call.
*/
class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
- implements KeyguardScreen, KeyguardUpdateMonitor.InfoCallback,
- KeyguardUpdateMonitor.SimStateCallback {
+ implements KeyguardScreen {
private static final boolean DEBUG = false;
private static final String TAG = "UnlockScreen";
@@ -73,7 +69,7 @@
*/
private boolean mEnableFallback;
- private StatusView mStatusView;
+ private KeyguardStatusViewManager mKeyguardStatusViewManager;
private LockPatternView mLockPatternView;
/**
@@ -93,12 +89,6 @@
}
};
- 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);
@@ -106,7 +96,6 @@
};
private Button mForgotPatternButton;
- private Button mEmergencyButton;
private int mCreationOrientation;
enum FooterMode {
@@ -181,19 +170,11 @@
inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
}
- 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);
+ mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,
+ mLockPatternUtils, mCallback);
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
- // emergency call buttons
- mEmergencyButton = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyButton.setFocusable(false); // touch only!
- mEmergencyButton.setOnClickListener(mEmergencyClick);
-
- refreshEmergencyButtonText();
-
mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton);
mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
mForgotPatternButton.setOnClickListener(mForgotPatternClick);
@@ -215,20 +196,10 @@
// assume normal footer mode for now
updateFooter(FooterMode.Normal);
- mUpdateMonitor.registerInfoCallback(this);
- mUpdateMonitor.registerSimStateCallback(this);
setFocusableInTouchMode(true);
-
- // until we get an update...
- mStatusView.setCarrierText(LockScreen.getCarrierString(
- mUpdateMonitor.getTelephonyPlmn(),
- mUpdateMonitor.getTelephonySpn()));
-
}
- private void refreshEmergencyButtonText() {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyButton);
- }
+
public void setEnableFallback(boolean state) {
if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
@@ -249,34 +220,6 @@
return result;
}
- // ---------- InfoCallback
-
- /** {@inheritDoc} */
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
- mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel);
- }
-
- /** {@inheritDoc} */
- public void onTimeChanged() {
- mStatusView.onTimeChanged();
- }
-
- /** {@inheritDoc} */
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- mStatusView.onRefreshCarrierInfo(plmn, spn);
- }
-
- /** {@inheritDoc} */
- public void onRingerModeChanged(int state) {
- // not currently used
- }
-
- // ---------- SimStateCallback
-
- /** {@inheritDoc} */
- public void onSimStateChanged(IccCard.State simState) {
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -319,12 +262,13 @@
mCountdownTimer.cancel();
mCountdownTimer = null;
}
+ mKeyguardStatusViewManager.onPause();
}
/** {@inheritDoc} */
public void onResume() {
// reset status
- mStatusView.resetStatusInfo(mUpdateMonitor, mLockPatternUtils);
+ mKeyguardStatusViewManager.onResume();
// reset lock pattern
mLockPatternView.enableInput();
@@ -354,7 +298,6 @@
updateFooter(FooterMode.Normal);
}
- refreshEmergencyButtonText();
}
/** {@inheritDoc} */
@@ -401,8 +344,8 @@
if (mLockPatternUtils.checkPattern(pattern)) {
mLockPatternView
.setDisplayMode(LockPatternView.DisplayMode.Correct);
- mStatusView.setInstructions("");
- mStatusView.updateStatusLines(true);
+ mKeyguardStatusViewManager.setInstructionText("");
+ mKeyguardStatusViewManager.updateStatusLines(true);
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
@@ -423,9 +366,9 @@
handleAttemptLockout(deadline);
} else {
// TODO mUnlockIcon.setVisibility(View.VISIBLE);
- mStatusView.setInstructions(
+ mKeyguardStatusViewManager.setInstructionText(
getContext().getString(R.string.lockscreen_pattern_wrong));
- mStatusView.updateStatusLines(true);
+ mKeyguardStatusViewManager.updateStatusLines(true);
mLockPatternView.postDelayed(
mCancelPatternRunnable,
PATTERN_CLEAR_TIMEOUT_MS);
@@ -449,18 +392,18 @@
@Override
public void onTick(long millisUntilFinished) {
int secondsRemaining = (int) (millisUntilFinished / 1000);
- mStatusView.setInstructions(getContext().getString(
+ mKeyguardStatusViewManager.setInstructionText(getContext().getString(
R.string.lockscreen_too_many_failed_attempts_countdown,
secondsRemaining));
- mStatusView.updateStatusLines(true);
+ mKeyguardStatusViewManager.updateStatusLines(true);
}
@Override
public void onFinish() {
mLockPatternView.setEnabled(true);
- mStatusView.setInstructions(getContext().getString(
+ mKeyguardStatusViewManager.setInstructionText(getContext().getString(
R.string.lockscreen_pattern_instructions));
- mStatusView.updateStatusLines(true);
+ mKeyguardStatusViewManager.updateStatusLines(true);
// TODO mUnlockIcon.setVisibility(View.VISIBLE);
mFailedPatternAttemptsSinceLastTimeout = 0;
if (mEnableFallback) {
@@ -472,7 +415,4 @@
}.start();
}
- public void onPhoneStateChanged(String newState) {
- refreshEmergencyButtonText();
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e0debf7..174f733 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -343,6 +343,13 @@
}
}
+ if (mActionBar != null) {
+ if (mActionMenuPresenterCallback == null) {
+ mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
+ }
+ mActionBar.setMenu(st.menu, mActionMenuPresenterCallback);
+ }
+
// Call callback, and return if it doesn't want to display menu.
// Creating the panel menu will involve a lot of manipulation;
@@ -356,13 +363,6 @@
}
st.refreshMenuContent = false;
-
- if (mActionBar != null) {
- if (mActionMenuPresenterCallback == null) {
- mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
- }
- mActionBar.setMenu(st.menu, mActionMenuPresenterCallback);
- }
}
// Callback and return if the callback does not want to show the menu
@@ -374,13 +374,13 @@
st.menu.startDispatchingItemsChanged();
return false;
}
- st.menu.startDispatchingItemsChanged();
// Set the proper keymap
KeyCharacterMap kmap = KeyCharacterMap.load(
event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD);
st.qwertyMode = kmap.getKeyboardType() != KeyCharacterMap.NUMERIC;
st.menu.setQwertyMode(st.qwertyMode);
+ st.menu.startDispatchingItemsChanged();
}
// Set other state
@@ -454,8 +454,6 @@
if (featureId == FEATURE_OPTIONS_PANEL && mActionBar != null &&
mActionBar.isOverflowReserved()) {
if (mActionBar.getVisibility() == View.VISIBLE) {
- // Invalidate the options menu, we want a prepare event that the app can respond to.
- invalidatePanelMenu(FEATURE_OPTIONS_PANEL);
mActionBar.showOverflowMenu();
}
} else {
@@ -664,6 +662,8 @@
if (savedActionViewStates.size() > 0) {
st.frozenActionViewState = savedActionViewStates;
}
+ // This will be started again when the panel is prepared.
+ st.menu.stopDispatchingItemsChanged();
st.menu.clear();
}
st.refreshMenuContent = true;
@@ -2040,13 +2040,14 @@
mActionModePopup = new PopupWindow(mContext, null,
com.android.internal.R.attr.actionModePopupWindowStyle);
mActionModePopup.setLayoutInScreenEnabled(true);
+ mActionModePopup.setLayoutInsetDecor(true);
mActionModePopup.setClippingEnabled(false);
mActionModePopup.setContentView(mActionModeView);
mActionModePopup.setWidth(MATCH_PARENT);
TypedValue heightValue = new TypedValue();
mContext.getTheme().resolveAttribute(
- com.android.internal.R.attr.actionBarSize, heightValue, false);
+ com.android.internal.R.attr.actionBarSize, heightValue, true);
final int height = TypedValue.complexToDimensionPixelSize(heightValue.data,
mContext.getResources().getDisplayMetrics());
mActionModePopup.setHeight(height);
@@ -2656,7 +2657,9 @@
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
public void run() {
- if (!isDestroyed()) {
+ // Invalidate if the panel menu hasn't been created before this.
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (!isDestroyed() && (st == null || st.menu == null)) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ae13ab5..b7f6adf 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2444,20 +2444,22 @@
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (down) {
- // If the power key down was already triggered, take the screenshot
- if (mPowerDownTriggered) {
- // Dismiss the power-key longpress
- mHandler.removeCallbacks(mPowerLongPress);
- mPowerKeyHandled = true;
+ if (isScreenOn) {
+ // If the power key down was already triggered, take the screenshot
+ if (mPowerDownTriggered) {
+ // Dismiss the power-key longpress
+ mHandler.removeCallbacks(mPowerLongPress);
+ mPowerKeyHandled = true;
- // Take the screenshot
- takeScreenshot();
+ // Take the screenshot
+ takeScreenshot();
- // Prevent the event from being passed through to the current activity
- result &= ~ACTION_PASS_TO_USER;
- break;
+ // Prevent the event from being passed through to the current activity
+ result &= ~ACTION_PASS_TO_USER;
+ break;
+ }
+ mVolumeDownTriggered = true;
}
- mVolumeDownTriggered = true;
} else {
mVolumeDownTriggered = false;
}
@@ -2541,17 +2543,18 @@
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
- // If the volume down key has been triggered, then just take the screenshot
- if (mVolumeDownTriggered) {
- // Take the screenshot
- takeScreenshot();
- mPowerKeyHandled = true;
+ if (isScreenOn) {
+ // If the volume down key has been triggered, then just take the screenshot
+ if (mVolumeDownTriggered) {
+ // Take the screenshot
+ takeScreenshot();
+ mPowerKeyHandled = true;
- // Prevent the event from being passed through to the current activity
- break;
+ // Prevent the event from being passed through to the current activity
+ break;
+ }
+ mPowerDownTriggered = true;
}
- mPowerDownTriggered = true;
-
ITelephony telephonyService = getTelephonyService();
boolean hungUp = false;
diff --git a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
index 7e8d547..f968bee 100644
--- a/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimPukUnlockScreen.java
@@ -24,11 +24,9 @@
import android.os.ServiceManager;
import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LockPatternUtils;
import android.text.Editable;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -42,7 +40,7 @@
* Displays a dialer like interface to unlock the SIM PUK.
*/
public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
- View.OnClickListener, KeyguardUpdateMonitor.InfoCallback {
+ View.OnClickListener {
private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
@@ -56,7 +54,6 @@
private TextView mFocusedEntry;
private TextView mOkButton;
- private Button mEmergencyCallButton;
private View mDelPukButton;
private View mDelPinButton;
@@ -69,6 +66,8 @@
private int mKeyboardHidden;
+ private KeyguardStatusViewManager mKeyguardStatusViewManager;
+
private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public SimPukUnlockScreen(Context context, Configuration configuration,
@@ -108,8 +107,6 @@
mDelPinButton = findViewById(R.id.pinDel);
mDelPinButton.setOnClickListener(this);
-
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
mOkButton = (TextView) findViewById(R.id.ok);
mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
@@ -119,12 +116,8 @@
requestFocus(mPukText);
- if (mLockPatternUtils.isEmergencyCallCapable()) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- mEmergencyCallButton.setOnClickListener(this);
- } else {
- mEmergencyCallButton.setVisibility(View.GONE);
- }
+ mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+ lockpatternutils, callback);
setFocusableInTouchMode(true);
}
@@ -141,7 +134,7 @@
/** {@inheritDoc} */
public void onPause() {
-
+ mKeyguardStatusViewManager.onPause();
}
/** {@inheritDoc} */
@@ -151,9 +144,7 @@
requestFocus(mPukText);
mPinText.setText("");
- if (mLockPatternUtils.isEmergencyCallCapable()) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- }
+ mKeyguardStatusViewManager.onResume();
}
/** {@inheritDoc} */
@@ -221,8 +212,6 @@
} else if (v == mPinText) {
requestFocus(mPinText);
mCallback.pokeWakelock();
- } else if (v == mEmergencyCallButton) {
- mCallback.takeEmergencyCallAction();
} else if (v == mOkButton) {
checkPuk();
}
@@ -446,25 +435,4 @@
}
}
- public void onPhoneStateChanged(String newState) {
- if (mLockPatternUtils.isEmergencyCallCapable()) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- }
- }
-
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
-
- }
-
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-
- }
-
- public void onRingerModeChanged(int state) {
-
- }
-
- public void onTimeChanged() {
-
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
index ec917f0..8bac969 100644
--- a/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -39,8 +39,7 @@
/**
* Displays a dialer like interface to unlock the SIM PIN.
*/
-public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener,
- KeyguardUpdateMonitor.InfoCallback {
+public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener {
private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
@@ -51,7 +50,6 @@
private TextView mPinText;
private TextView mOkButton;
- private Button mEmergencyCallButton;
private View mBackSpaceButton;
@@ -66,6 +64,8 @@
private int mKeyboardHidden;
+ private KeyguardStatusViewManager mKeyguardStatusViewManager;
+
private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public SimUnlockScreen(Context context, Configuration configuration,
@@ -99,9 +99,8 @@
mOkButton.setOnClickListener(this);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyCallButton.setOnClickListener(this);
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
+ lockpatternutils, callback);
setFocusableInTouchMode(true);
}
@@ -113,7 +112,7 @@
/** {@inheritDoc} */
public void onPause() {
-
+ mKeyguardStatusViewManager.onPause();
}
/** {@inheritDoc} */
@@ -126,7 +125,7 @@
mPinText.setText("");
mEnteredDigits = 0;
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+ mKeyguardStatusViewManager.onResume();
}
/** {@inheritDoc} */
@@ -183,8 +182,6 @@
mEnteredDigits--;
}
mCallback.pokeWakelock();
- } else if (v == mEmergencyCallButton) {
- mCallback.takeEmergencyCallAction();
} else if (v == mOkButton) {
checkPin();
}
@@ -401,24 +398,4 @@
return digit;
}
}
-
- public void onPhoneStateChanged(String newState) {
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
- }
-
- public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
-
- }
-
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-
- }
-
- public void onRingerModeChanged(int state) {
-
- }
-
- public void onTimeChanged() {
-
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
deleted file mode 100644
index 79f81ff..0000000
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2010 Google Inc. All Rights Reserved.
-
-package com.android.internal.policy.impl;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-import com.google.android.util.AbstractMessageParser.Resources;
-
-import java.util.Date;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-
-class StatusView {
- public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
- public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
- public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
- public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
-
- private String mDateFormatString;
-
- private TextView mCarrier;
- private TextView mDate;
-
- // are we showing battery information?
- private boolean mShowingBatteryInfo = false;
-
- // last known plugged in state
- private boolean mPluggedIn = false;
-
- // last known battery level
- private int mBatteryLevel = 100;
-
- private String mInstructions = null;
- private TextView mStatus1;
- private TextView mOwnerInfo;
-
- private boolean mHasCarrier;
- private boolean mHasDate;
-
- private View mView;
-
- private TextView mAlarmStatus;
- private LockPatternUtils mLockPatternUtils;
- private int mHelpMessageId;
- private int mHelpIconId;
- private KeyguardUpdateMonitor mUpdateMonitor;
-
- private View findViewById(int id) {
- return mView.findViewById(id);
- }
-
- private Context getContext() {
- return mView.getContext();
- }
-
- void setInstructions(String instructions) {
- mInstructions = instructions;
- }
-
- void setCarrierText(CharSequence carrierText) {
- if (mCarrier != null) {
- mCarrier.setText(carrierText);
- }
- }
-
- void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
- mShowingBatteryInfo = showBatteryInfo;
- mPluggedIn = pluggedIn;
- mBatteryLevel = batteryLevel;
- updateStatusLines(true);
- }
-
- void onTimeChanged() {
- refreshTimeAndDateDisplay();
- }
-
- public void onRingerModeChanged(int state) {
- }
-
- void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- setCarrierText(LockScreen.getCarrierString(plmn, spn));
- }
-
- public StatusView(View view, KeyguardUpdateMonitor updateMonitor,
- LockPatternUtils lockPatternUtils) {
- mView = view;
- mCarrier = (TextView) findViewById(R.id.carrier);
- mHasCarrier = (mCarrier != null);
- mDate = (TextView) findViewById(R.id.date);
- mHasDate = (mDate != null);
- mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
-
- refreshTimeAndDateDisplay();
-
- mStatus1 = (TextView) findViewById(R.id.status1);
- mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
- mAlarmStatus.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
- mOwnerInfo = (TextView) findViewById(R.id.propertyOf);
-
- resetStatusInfo(updateMonitor, lockPatternUtils);
-
- // Required to get Marquee to work.
- if (mHasCarrier) {
- mCarrier.setSelected(true);
- mCarrier.setTextColor(0xffffffff);
- }
- }
-
- void resetStatusInfo(KeyguardUpdateMonitor updateMonitor, LockPatternUtils lockPatternUtils) {
- mInstructions = null;
- mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
- mPluggedIn = updateMonitor.isDevicePluggedIn();
- mBatteryLevel = updateMonitor.getBatteryLevel();
- updateStatusLines(true);
- }
-
- void setInstructionText(int stringId) {
- mStatus1.setText(stringId);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
- mStatus1.setVisibility(stringId != 0 ? View.VISIBLE : View.INVISIBLE);
- }
-
- void setInstructionText(String string) {
- mStatus1.setText(string);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
- mStatus1.setVisibility(TextUtils.isEmpty(string) ? View.INVISIBLE : View.VISIBLE);
- }
-
- void setCarrierText(int stringId) {
- mCarrier.setText(stringId);
- }
- void setCarrierText(String string) {
- mCarrier.setText(string);
- }
-
- /**
- * Update the status lines based on these rules:
- * AlarmStatus: Alarm state always gets it's own line.
- * Status1 is shared between help, battery status and generic unlock instructions,
- * prioritized in that order.
- * @param showStatusLines status lines are shown if true
- */
- void updateStatusLines(boolean showStatusLines) {
- if (!showStatusLines) {
- mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
- mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
- return;
- }
-
- // Update owner info
- 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
- String nextAlarm = mLockPatternUtils.getNextAlarm();
- if (!TextUtils.isEmpty(nextAlarm)) {
- mAlarmStatus.setText(nextAlarm);
- mAlarmStatus.setVisibility(View.VISIBLE);
- } else {
- mAlarmStatus.setVisibility(View.GONE);
- }
-
- // Update Status1
- if (!TextUtils.isEmpty(mInstructions)) {
- // Instructions only
- mStatus1.setText(mInstructions);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
- mStatus1.setVisibility(View.VISIBLE);
- } else if (mShowingBatteryInfo) {
- // Battery status
- if (mPluggedIn) {
- // Charging or charged
- if (mUpdateMonitor.isDeviceCharged()) {
- mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
- } else {
- mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in,
- mBatteryLevel));
- }
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(CHARGING_ICON, 0, 0, 0);
- mStatus1.setVisibility(View.VISIBLE);
- } else if (mBatteryLevel < KeyguardUpdateMonitor.LOW_BATTERY_THRESHOLD) {
- // Battery is low
- mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery));
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(BATTERY_LOW_ICON, 0, 0, 0);
- mStatus1.setVisibility(View.VISIBLE);
- } 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 {
- mStatus1.setVisibility(View.INVISIBLE);
- }
- }
-
- void setHelpMessage(int messageId, int iconId) {
- mHelpMessageId = messageId;
- mHelpIconId = iconId;
- }
-
- void refreshTimeAndDateDisplay() {
- if (mHasDate) {
- mDate.setText(DateFormat.format(mDateFormatString, new Date()));
- }
- }
-
-}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index a0407b9..fa49592 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -21,7 +21,8 @@
libhardware \
libhardware_legacy \
libeffects \
- libdl
+ libdl \
+ libpowermanager
LOCAL_STATIC_LIBRARIES := \
libcpustats \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0323fe0..ec45530 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -53,6 +53,7 @@
#include <audio_effects/effect_visualizer.h>
#include <cpustats/ThreadCpuUsage.h>
+#include <powermanager/PowerManager.h>
// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
// ----------------------------------------------------------------------------
@@ -887,14 +888,18 @@
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
: Thread(false),
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
- mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device)
+ mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
+ mDevice(device)
{
+ mDeathRecipient = new PMDeathRecipient(this);
}
AudioFlinger::ThreadBase::~ThreadBase()
{
mParamCond.broadcast();
mNewParameters.clear();
+ // do not lock the mutex in destructor
+ releaseWakeLock_l();
}
void AudioFlinger::ThreadBase::exit()
@@ -1043,6 +1048,88 @@
return NO_ERROR;
}
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+ write(fd, buffer, strlen(buffer));
+
+ for (size_t i = 0; i < mEffectChains.size(); ++i) {
+ sp<EffectChain> chain = mEffectChains[i];
+ if (chain != 0) {
+ chain->dump(fd, args);
+ }
+ }
+ return NO_ERROR;
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ acquireWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
+{
+ if (mPowerManager == 0) {
+ // use checkService() to avoid blocking if power service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("power"));
+ if (binder == 0) {
+ LOGW("Thread %s cannot connect to the power manager service", mName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16(mName));
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ LOGV("acquireWakeLock_l() %s status %d", mName, status);
+ }
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock_l()
+{
+ if (mWakeLockToken != 0) {
+ LOGV("releaseWakeLock_l() %s", mName);
+ if (mPowerManager != 0) {
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ }
+ mWakeLockToken.clear();
+ }
+}
+
+void AudioFlinger::ThreadBase::clearPowerManager()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+ mPowerManager.clear();
+}
+
+void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ thread->clearPowerManager();
+ }
+ LOGW("power manager service died !!!");
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
@@ -1053,6 +1140,8 @@
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
{
+ snprintf(mName, kNameLength, "AudioOut_%d", id);
+
readOutputParameters();
mMasterVolume = mAudioFlinger->masterVolume();
@@ -1111,24 +1200,6 @@
return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
- write(fd, buffer, strlen(buffer));
-
- for (size_t i = 0; i < mEffectChains.size(); ++i) {
- sp<EffectChain> chain = mEffectChains[i];
- if (chain != 0) {
- chain->dump(fd, args);
- }
- }
- return NO_ERROR;
-}
-
status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -1169,12 +1240,7 @@
void AudioFlinger::PlaybackThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Playback Thread %p", this);
-
- run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+ run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1521,6 +1587,8 @@
const CentralTendencyStatistics& stats = cpu.statistics();
#endif
+ acquireWakeLock();
+
while (!exitPending())
{
#ifdef DEBUG_CPU_USAGE
@@ -1584,10 +1652,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
// wait until we have something to do...
LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -1688,6 +1758,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("MixerThread %p exiting", this);
return false;
}
@@ -2175,6 +2247,8 @@
// hardware resources as soon as possible
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
+ acquireWakeLock();
+
while (!exitPending())
{
bool rampVolume;
@@ -2214,9 +2288,11 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -2435,6 +2511,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("DirectOutputThread %p exiting", this);
return false;
}
@@ -2560,6 +2638,8 @@
uint32_t sleepTime = idleSleepTime;
Vector< sp<EffectChain> > effectChains;
+ acquireWakeLock();
+
while (!exitPending())
{
processConfigEvents();
@@ -2600,9 +2680,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
+
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
property_get("ro.audio.silent", value, "0");
@@ -2689,6 +2772,8 @@
effectChains.clear();
}
+ releaseWakeLock();
+
return false;
}
@@ -3813,6 +3898,9 @@
mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{
mType = ThreadBase::RECORD;
+
+ snprintf(mName, kNameLength, "AudioIn_%d", id);
+
mReqChannelCount = popcount(channels);
mReqSampleRate = sampleRate;
readInputParameters();
@@ -3830,12 +3918,7 @@
void AudioFlinger::RecordThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Record Thread %p", this);
-
- run(buffer, PRIORITY_URGENT_AUDIO);
+ run(mName, PRIORITY_URGENT_AUDIO);
}
bool AudioFlinger::RecordThread::threadLoop()
@@ -3846,6 +3929,8 @@
nsecs_t lastWarning = 0;
+ acquireWakeLock();
+
// start recording
while (!exitPending()) {
@@ -3862,10 +3947,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("RecordThread: loop stopping");
// go to sleep
mWaitWorkCV.wait(mLock);
LOGV("RecordThread: loop starting");
+ acquireWakeLock_l();
continue;
}
if (mActiveTrack != 0) {
@@ -3906,8 +3993,6 @@
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
- // enable changes in effect chain
- unlockEffectChains(effectChains);
buffer.frameCount = mFrameCount;
if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
@@ -4007,9 +4092,9 @@
// clear the overflow.
usleep(kRecordThreadSleepUs);
}
- } else {
- unlockEffectChains(effectChains);
}
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
effectChains.clear();
}
@@ -4020,6 +4105,8 @@
mStartStopCond.broadcast();
+ releaseWakeLock();
+
LOGV("RecordThread %p exiting", this);
return false;
}
@@ -4178,6 +4265,7 @@
write(fd, result.string(), result.size());
dumpBase(fd, args);
+ dumpEffectChains(fd, args);
return NO_ERROR;
}
@@ -5579,13 +5667,11 @@
}
}
- // Release effect engine here so that it is done immediately. Otherwise it will be released
- // by the destructor when the last strong reference on the this object is released which can
- // happen after next process is called on this effect.
- if (size == 0 && mEffectInterface != NULL) {
- // release effect engine
- EffectRelease(mEffectInterface);
- mEffectInterface = NULL;
+ // Prevent calls to process() and other functions on effect interface from now on.
+ // The effect engine will be released by the destructor when the last strong reference on
+ // this object is released which can happen after next process is called.
+ if (size == 0) {
+ mState = DESTROYED;
}
return size;
@@ -5635,7 +5721,7 @@
mState = IDLE;
}
break;
- default: //IDLE , ACTIVE
+ default: //IDLE , ACTIVE, DESTROYED
break;
}
}
@@ -5644,7 +5730,7 @@
{
Mutex::Autolock _l(mLock);
- if (mEffectInterface == NULL ||
+ if (mState == DESTROYED || mEffectInterface == NULL ||
mConfig.inputCfg.buffer.raw == NULL ||
mConfig.outputCfg.buffer.raw == NULL) {
return;
@@ -5820,6 +5906,12 @@
return status;
}
+status_t AudioFlinger::EffectModule::stop()
+{
+ Mutex::Autolock _l(mLock);
+ return stop_l();
+}
+
status_t AudioFlinger::EffectModule::stop_l()
{
if (mEffectInterface == NULL) {
@@ -5856,7 +5948,7 @@
Mutex::Autolock _l(mLock);
// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
- if (mEffectInterface == NULL) {
+ if (mState == DESTROYED || mEffectInterface == NULL) {
return NO_INIT;
}
status_t status = (*mEffectInterface)->command(mEffectInterface,
@@ -5905,6 +5997,8 @@
case ACTIVE:
mState = STOPPING;
break;
+ case DESTROYED:
+ return NO_ERROR; // simply ignore as we are being destroyed
}
for (size_t i = 1; i < mHandles.size(); i++) {
sp<EffectHandle> h = mHandles[i].promote();
@@ -5926,6 +6020,7 @@
case IDLE:
case STOPPING:
case STOPPED:
+ case DESTROYED:
default:
return false;
}
@@ -5941,6 +6036,7 @@
return true;
case IDLE:
case STARTING:
+ case DESTROYED:
default:
return false;
}
@@ -6542,6 +6638,10 @@
for (i = 0; i < size; i++) {
if (effect == mEffects[i]) {
+ // calling stop here will remove pre-processing effect from the audio HAL.
+ // This is safe as we hold the EffectChain mutex which guarantees that we are not in
+ // the middle of a read from audio HAL
+ mEffects[i]->stop();
if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
delete[] effect->inBuffer();
} else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fff4f06..7b6215f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,6 +43,8 @@
#include "AudioBufferProvider.h"
+#include <powermanager/IPowerManager.h>
+
namespace android {
class audio_track_cblk_t;
@@ -285,6 +287,9 @@
};
status_t dumpBase(int fd, const Vector<String16>& args);
+ status_t dumpEffectChains(int fd, const Vector<String16>& args);
+
+ void clearPowerManager();
// base for record and playback
class TrackBase : public AudioBufferProvider, public RefBase {
@@ -385,6 +390,21 @@
int mParam;
};
+ class PMDeathRecipient : public IBinder::DeathRecipient {
+ public:
+ PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
+ virtual ~PMDeathRecipient() {}
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ PMDeathRecipient(const PMDeathRecipient&);
+ PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+ wp<ThreadBase> mThread;
+ };
+
virtual status_t initCheck() const = 0;
int type() const { return mType; }
uint32_t sampleRate() const;
@@ -461,6 +481,11 @@
protected:
+ void acquireWakeLock();
+ void acquireWakeLock_l();
+ void releaseWakeLock();
+ void releaseWakeLock_l();
+
friend class Track;
friend class TrackBase;
friend class PlaybackThread;
@@ -489,6 +514,11 @@
Vector< sp<EffectChain> > mEffectChains;
uint32_t mDevice; // output device for PlaybackThread
// input + output devices for RecordThread
+ static const int kNameLength = 32;
+ char mName[kNameLength];
+ sp<IPowerManager> mPowerManager;
+ sp<IBinder> mWakeLockToken;
+ sp<PMDeathRecipient> mDeathRecipient;
};
// --- PlaybackThread ---
@@ -724,7 +754,6 @@
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
status_t dumpTracks(int fd, const Vector<String16>& args);
- status_t dumpEffectChains(int fd, const Vector<String16>& args);
SortedVector< sp<Track> > mTracks;
// mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
@@ -995,7 +1024,8 @@
STARTING,
ACTIVE,
STOPPING,
- STOPPED
+ STOPPED,
+ DESTROYED
};
int id() { return mId; }
@@ -1040,6 +1070,7 @@
status_t setDevice(uint32_t device);
status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
status_t setMode(uint32_t mode);
+ status_t stop();
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd1e153..6d06d83 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -497,6 +497,43 @@
return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
}
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+
+ if (mpAudioPolicy == NULL) {
+ *count = 0;
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+
+ size_t index;
+ for (index = 0; index < mInputs.size(); index++) {
+ if (mInputs.valueAt(index)->mSessionId == audioSession) {
+ break;
+ }
+ }
+ if (index == mInputs.size()) {
+ *count = 0;
+ return BAD_VALUE;
+ }
+ Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+ for (size_t i = 0; i < effects.size(); i++) {
+ effect_descriptor_t desc = effects[i]->descriptor();
+ if (i < *count) {
+ memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+ }
+ }
+ if (effects.size() > *count) {
+ status = NO_MEMORY;
+ }
+ *count = effects.size();
+ return status;
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
IPCThreadState::self()->getCallingPid());
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 62ad29e..834b794 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -104,6 +104,9 @@
virtual status_t unregisterEffect(int id);
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a583aad..31544b3 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -38,6 +38,7 @@
typedef void (*data_callback)(int32_t msgType,
const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata,
void* user);
typedef void (*data_callback_timestamp)(nsecs_t timestamp,
@@ -386,7 +387,10 @@
if (mDevice->ops->get_parameters) {
char *temp = mDevice->ops->get_parameters(mDevice);
String8 str_parms(temp);
- free(temp);
+ if (mDevice->ops->put_parameters)
+ mDevice->ops->put_parameters(mDevice, temp);
+ else
+ free(temp);
parms.unflatten(str_parms);
}
return parms;
@@ -439,6 +443,7 @@
static void __data_cb(int32_t msg_type,
const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata,
void *user)
{
LOGV("%s", __FUNCTION__);
@@ -450,7 +455,7 @@
index, mem->mNumBufs);
return;
}
- __this->mDataCb(msg_type, mem->mBuffers[index], __this->mCbUser);
+ __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
}
static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index 07b5a37..863f19e 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -180,7 +180,7 @@
// Notify the client of a new frame.
if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
// Advance the buffer pointer.
mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
@@ -290,14 +290,14 @@
sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
FakeCamera cam(w, h);
cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
}
if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
}
return NO_ERROR;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 96b26e7..b03649e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -988,7 +988,7 @@
}
void CameraService::Client::dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr, void* user) {
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
LOG2("dataCallback(%d)", msgType);
sp<Client> client = getClientFromCookie(user);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c5fefb8..af7f06e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -140,7 +140,8 @@
// these are static callback functions
static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
- static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+ static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata, void* user);
static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
// convert client from cookie
static sp<Client> getClientFromCookie(void* user);
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index ca2540b..7ea3de2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -460,6 +460,17 @@
mExcludedDevices = devices;
}
+bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
+ if (test_bit(scanCode, device->keyBitmask)) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 695dfdf..293a1a0 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -195,6 +195,7 @@
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
uint8_t* outFlags) const = 0;
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
@@ -246,6 +247,7 @@
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
virtual bool hasLed(int32_t deviceId, int32_t led) const;
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 039b003..af13945 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -998,8 +998,7 @@
void InputDispatcher::resetTargetsLocked() {
mCurrentInputTargetsValid = false;
mCurrentInputTargets.clear();
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
- mInputTargetWaitApplicationHandle.clear();
+ resetANRTimeoutsLocked();
}
void InputDispatcher::commitTargetsLocked() {
@@ -1110,6 +1109,7 @@
// Reset input target wait timeout.
mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+ mInputTargetWaitApplicationHandle.clear();
}
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
@@ -3226,8 +3226,14 @@
AutoMutex _l(mLock);
if (inputApplicationHandle != NULL && inputApplicationHandle->update()) {
- mFocusedApplicationHandle = inputApplicationHandle;
- } else {
+ if (mFocusedApplicationHandle != inputApplicationHandle) {
+ if (mFocusedApplicationHandle != NULL) {
+ resetTargetsLocked();
+ }
+ mFocusedApplicationHandle = inputApplicationHandle;
+ }
+ } else if (mFocusedApplicationHandle != NULL) {
+ resetTargetsLocked();
mFocusedApplicationHandle.clear();
}
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index c9fac81..db312ad 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -151,30 +151,6 @@
return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
}
-static uint32_t getButtonStateForScanCode(int32_t scanCode) {
- // Currently all buttons are mapped to the primary button.
- switch (scanCode) {
- 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_FORWARD:
- case BTN_EXTRA:
- return AMOTION_EVENT_BUTTON_FORWARD;
- case BTN_BACK:
- return AMOTION_EVENT_BUTTON_BACK;
- case BTN_TASK:
- default:
- return 0;
- }
-}
-
// Returns true if the pointer should be reported as being down given the specified
// button states. This determines whether the event is reported as a touch event.
static bool isPointerDown(int32_t buttonState) {
@@ -1007,6 +983,378 @@
}
+// --- CursorButtonAccumulator ---
+
+CursorButtonAccumulator::CursorButtonAccumulator() {
+ clearButtons();
+}
+
+void CursorButtonAccumulator::clearButtons() {
+ mBtnLeft = 0;
+ mBtnRight = 0;
+ mBtnMiddle = 0;
+ mBtnBack = 0;
+ mBtnSide = 0;
+ mBtnForward = 0;
+ mBtnExtra = 0;
+ mBtnTask = 0;
+}
+
+void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->scanCode) {
+ case BTN_LEFT:
+ mBtnLeft = rawEvent->value;
+ break;
+ case BTN_RIGHT:
+ mBtnRight = rawEvent->value;
+ break;
+ case BTN_MIDDLE:
+ mBtnMiddle = rawEvent->value;
+ break;
+ case BTN_BACK:
+ mBtnBack = rawEvent->value;
+ break;
+ case BTN_SIDE:
+ mBtnSide = rawEvent->value;
+ break;
+ case BTN_FORWARD:
+ mBtnForward = rawEvent->value;
+ break;
+ case BTN_EXTRA:
+ mBtnExtra = rawEvent->value;
+ break;
+ case BTN_TASK:
+ mBtnTask = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t CursorButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnLeft) {
+ result |= AMOTION_EVENT_BUTTON_PRIMARY;
+ }
+ if (mBtnRight) {
+ result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ }
+ if (mBtnMiddle) {
+ result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ }
+ if (mBtnBack || mBtnSide) {
+ result |= AMOTION_EVENT_BUTTON_BACK;
+ }
+ if (mBtnForward || mBtnExtra) {
+ result |= AMOTION_EVENT_BUTTON_FORWARD;
+ }
+ return result;
+}
+
+
+// --- CursorMotionAccumulator ---
+
+CursorMotionAccumulator::CursorMotionAccumulator() :
+ mHaveRelWheel(false), mHaveRelHWheel(false) {
+ clearRelativeAxes();
+}
+
+void CursorMotionAccumulator::configure(InputDevice* device) {
+ mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
+ mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
+}
+
+void CursorMotionAccumulator::clearRelativeAxes() {
+ mRelX = 0;
+ mRelY = 0;
+ mRelWheel = 0;
+ mRelHWheel = 0;
+}
+
+void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_REL) {
+ switch (rawEvent->scanCode) {
+ case REL_X:
+ mRelX = rawEvent->value;
+ break;
+ case REL_Y:
+ mRelY = rawEvent->value;
+ break;
+ case REL_WHEEL:
+ mRelWheel = rawEvent->value;
+ break;
+ case REL_HWHEEL:
+ mRelHWheel = rawEvent->value;
+ break;
+ }
+ }
+}
+
+
+// --- TouchButtonAccumulator ---
+
+TouchButtonAccumulator::TouchButtonAccumulator() :
+ mHaveBtnTouch(false) {
+ clearButtons();
+}
+
+void TouchButtonAccumulator::configure(InputDevice* device) {
+ mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH);
+}
+
+void TouchButtonAccumulator::clearButtons() {
+ mBtnTouch = 0;
+ mBtnStylus = 0;
+ mBtnStylus2 = 0;
+ mBtnToolFinger = 0;
+ mBtnToolPen = 0;
+ mBtnToolRubber = 0;
+}
+
+void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_KEY) {
+ switch (rawEvent->scanCode) {
+ case BTN_TOUCH:
+ mBtnTouch = rawEvent->value;
+ break;
+ case BTN_STYLUS:
+ mBtnStylus = rawEvent->value;
+ break;
+ case BTN_STYLUS2:
+ mBtnStylus2 = rawEvent->value;
+ break;
+ case BTN_TOOL_FINGER:
+ mBtnToolFinger = rawEvent->value;
+ break;
+ case BTN_TOOL_PEN:
+ mBtnToolPen = rawEvent->value;
+ break;
+ case BTN_TOOL_RUBBER:
+ mBtnToolRubber = rawEvent->value;
+ break;
+ }
+ }
+}
+
+uint32_t TouchButtonAccumulator::getButtonState() const {
+ uint32_t result = 0;
+ if (mBtnStylus) {
+ result |= AMOTION_EVENT_BUTTON_SECONDARY;
+ }
+ if (mBtnStylus2) {
+ result |= AMOTION_EVENT_BUTTON_TERTIARY;
+ }
+ return result;
+}
+
+int32_t TouchButtonAccumulator::getToolType() const {
+ if (mBtnToolRubber) {
+ return AMOTION_EVENT_TOOL_TYPE_ERASER;
+ }
+ if (mBtnToolPen) {
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ if (mBtnToolFinger) {
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+bool TouchButtonAccumulator::isActive() const {
+ return mBtnTouch || mBtnToolFinger || mBtnToolPen
+ || mBtnToolRubber || mBtnStylus || mBtnStylus2;
+}
+
+bool TouchButtonAccumulator::isHovering() const {
+ return mHaveBtnTouch && !mBtnTouch;
+}
+
+
+// --- SingleTouchMotionAccumulator ---
+
+SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
+ clearAbsoluteAxes();
+}
+
+void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
+ mAbsX = 0;
+ mAbsY = 0;
+ mAbsPressure = 0;
+ mAbsToolWidth = 0;
+ mAbsDistance = 0;
+}
+
+void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ switch (rawEvent->scanCode) {
+ case ABS_X:
+ mAbsX = rawEvent->value;
+ break;
+ case ABS_Y:
+ mAbsY = rawEvent->value;
+ break;
+ case ABS_PRESSURE:
+ mAbsPressure = rawEvent->value;
+ break;
+ case ABS_TOOL_WIDTH:
+ mAbsToolWidth = rawEvent->value;
+ break;
+ case ABS_DISTANCE:
+ mAbsDistance = rawEvent->value;
+ break;
+ }
+ }
+}
+
+
+// --- MultiTouchMotionAccumulator ---
+
+MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
+ mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
+}
+
+MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
+ delete[] mSlots;
+}
+
+void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
+ mSlotCount = slotCount;
+ mUsingSlotsProtocol = usingSlotsProtocol;
+
+ delete[] mSlots;
+ mSlots = new Slot[slotCount];
+}
+
+void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
+ for (size_t i = 0; i < mSlotCount; i++) {
+ mSlots[i].clearIfInUse();
+ }
+ mCurrentSlot = initialSlot;
+}
+
+void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_ABS) {
+ bool newSlot = false;
+ if (mUsingSlotsProtocol) {
+ if (rawEvent->scanCode == ABS_MT_SLOT) {
+ mCurrentSlot = rawEvent->value;
+ newSlot = true;
+ }
+ } else if (mCurrentSlot < 0) {
+ mCurrentSlot = 0;
+ }
+
+ if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+#if DEBUG_POINTERS
+ if (newSlot) {
+ LOGW("MultiTouch device emitted invalid slot index %d but it "
+ "should be between 0 and %d; ignoring this slot.",
+ mCurrentSlot, mSlotCount - 1);
+ }
+#endif
+ } else {
+ Slot* slot = &mSlots[mCurrentSlot];
+
+ switch (rawEvent->scanCode) {
+ case ABS_MT_POSITION_X:
+ slot->mInUse = true;
+ slot->mAbsMTPositionX = rawEvent->value;
+ break;
+ case ABS_MT_POSITION_Y:
+ slot->mInUse = true;
+ slot->mAbsMTPositionY = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMajor = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTTouchMinor = rawEvent->value;
+ slot->mHaveAbsMTTouchMinor = true;
+ break;
+ case ABS_MT_WIDTH_MAJOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMajor = rawEvent->value;
+ break;
+ case ABS_MT_WIDTH_MINOR:
+ slot->mInUse = true;
+ slot->mAbsMTWidthMinor = rawEvent->value;
+ slot->mHaveAbsMTWidthMinor = true;
+ break;
+ case ABS_MT_ORIENTATION:
+ slot->mInUse = true;
+ slot->mAbsMTOrientation = rawEvent->value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ if (mUsingSlotsProtocol && rawEvent->value < 0) {
+ slot->clearIfInUse();
+ } else {
+ slot->mInUse = true;
+ slot->mAbsMTTrackingId = rawEvent->value;
+ }
+ break;
+ case ABS_MT_PRESSURE:
+ slot->mInUse = true;
+ slot->mAbsMTPressure = rawEvent->value;
+ break;
+ case ABS_MT_TOOL_TYPE:
+ slot->mInUse = true;
+ slot->mAbsMTToolType = rawEvent->value;
+ slot->mHaveAbsMTToolType = true;
+ break;
+ }
+ }
+ } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
+ // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+ mCurrentSlot += 1;
+ }
+}
+
+
+// --- MultiTouchMotionAccumulator::Slot ---
+
+MultiTouchMotionAccumulator::Slot::Slot() {
+ clear();
+}
+
+void MultiTouchMotionAccumulator::Slot::clearIfInUse() {
+ if (mInUse) {
+ clear();
+ }
+}
+
+void MultiTouchMotionAccumulator::Slot::clear() {
+ mInUse = false;
+ mHaveAbsMTTouchMinor = false;
+ mHaveAbsMTWidthMinor = false;
+ mHaveAbsMTToolType = false;
+ mAbsMTPositionX = 0;
+ mAbsMTPositionY = 0;
+ mAbsMTTouchMajor = 0;
+ mAbsMTTouchMinor = 0;
+ mAbsMTWidthMajor = 0;
+ mAbsMTWidthMinor = 0;
+ mAbsMTOrientation = 0;
+ mAbsMTTrackingId = -1;
+ mAbsMTPressure = 0;
+ mAbsMTToolType = 0;
+ mAbsMTDistance = 0;
+}
+
+int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
+ if (mHaveAbsMTToolType) {
+ switch (mAbsMTToolType) {
+ case MT_TOOL_FINGER:
+ return AMOTION_EVENT_TOOL_TYPE_FINGER;
+ case MT_TOOL_PEN:
+ return AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ }
+ }
+ return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+}
+
+
// --- InputMapper ---
InputMapper::InputMapper(InputDevice* device) :
@@ -1157,7 +1505,10 @@
getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
mParameters.orientationAware);
- mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
+ mParameters.associatedDisplayId = -1;
+ if (mParameters.orientationAware) {
+ mParameters.associatedDisplayId = 0;
+ }
}
void KeyboardInputMapper::dumpParameters(String8& dump) {
@@ -1229,7 +1580,7 @@
if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
int32_t orientation;
if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- NULL, NULL, & orientation)) {
+ false /*external*/, NULL, NULL, & orientation)) {
orientation = DISPLAY_ORIENTATION_0;
}
@@ -1399,10 +1750,10 @@
}
info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
- if (mHaveVWheel) {
+ if (mCursorMotionAccumulator.haveRelativeVWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
- if (mHaveHWheel) {
+ if (mCursorMotionAccumulator.haveRelativeHWheel()) {
info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
}
}
@@ -1416,8 +1767,10 @@
dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
- dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
+ dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
+ toString(mCursorMotionAccumulator.haveRelativeVWheel()));
+ dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
+ toString(mCursorMotionAccumulator.haveRelativeHWheel()));
dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
@@ -1430,6 +1783,8 @@
InputMapper::configure(config, changes);
if (!changes) { // first time only
+ mCursorMotionAccumulator.configure(getDevice());
+
// Configure basic parameters.
configureParameters();
@@ -1454,9 +1809,6 @@
mVWheelScale = 1.0f;
mHWheelScale = 1.0f;
-
- mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
- mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
@@ -1481,8 +1833,10 @@
getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
mParameters.orientationAware);
- mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
- || mParameters.orientationAware ? 0 : -1;
+ mParameters.associatedDisplayId = -1;
+ if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
+ mParameters.associatedDisplayId = 0;
+ }
}
void CursorInputMapper::dumpParameters(String8& dump) {
@@ -1506,7 +1860,8 @@
}
void CursorInputMapper::initializeLocked() {
- mAccumulator.clear();
+ mCursorButtonAccumulator.clearButtons();
+ mCursorMotionAccumulator.clearRelativeAxes();
mLocked.buttonState = 0;
mLocked.downTime = 0;
@@ -1532,10 +1887,8 @@
// Synthesize button up event on reset.
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
- mAccumulator.clear();
- mAccumulator.buttonDown = 0;
- mAccumulator.buttonUp = buttonState;
- mAccumulator.fields = Accumulator::FIELD_BUTTONS;
+ mCursorButtonAccumulator.clearButtons();
+ mCursorMotionAccumulator.clearRelativeAxes();
sync(when);
}
@@ -1543,64 +1896,15 @@
}
void CursorInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown = buttonState;
- mAccumulator.buttonUp = 0;
- } else {
- mAccumulator.buttonDown = 0;
- mAccumulator.buttonUp = buttonState;
- }
- mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
+ mCursorButtonAccumulator.process(rawEvent);
+ mCursorMotionAccumulator.process(rawEvent);
- // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
- // we need to ensure that we report the up/down promptly.
- sync(rawEvent->when);
- break;
- }
- break;
- }
-
- case EV_REL:
- switch (rawEvent->scanCode) {
- case REL_X:
- mAccumulator.fields |= Accumulator::FIELD_REL_X;
- mAccumulator.relX = rawEvent->value;
- break;
- case REL_Y:
- mAccumulator.fields |= Accumulator::FIELD_REL_Y;
- mAccumulator.relY = rawEvent->value;
- break;
- case REL_WHEEL:
- mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
- mAccumulator.relWheel = rawEvent->value;
- break;
- case REL_HWHEEL:
- mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
- mAccumulator.relHWheel = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void CursorInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
int32_t motionEventAction;
int32_t lastButtonState, currentButtonState;
PointerProperties pointerProperties;
@@ -1611,34 +1915,21 @@
AutoMutex _l(mLock);
lastButtonState = mLocked.buttonState;
+ currentButtonState = mCursorButtonAccumulator.getButtonState();
+ mLocked.buttonState = currentButtonState;
- bool down, downChanged;
- bool wasDown = isPointerDown(mLocked.buttonState);
- bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
- if (buttonsChanged) {
- mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
- & ~mAccumulator.buttonUp;
-
- down = isPointerDown(mLocked.buttonState);
-
- if (!wasDown && down) {
- mLocked.downTime = when;
- downChanged = true;
- } else if (wasDown && !down) {
- downChanged = true;
- } else {
- downChanged = false;
- }
+ bool wasDown = isPointerDown(lastButtonState);
+ bool down = isPointerDown(currentButtonState);
+ bool downChanged;
+ if (!wasDown && down) {
+ mLocked.downTime = when;
+ downChanged = true;
+ } else if (wasDown && !down) {
+ downChanged = true;
} else {
- down = wasDown;
downChanged = false;
}
-
- currentButtonState = mLocked.buttonState;
-
downTime = mLocked.downTime;
- float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
- float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
if (downChanged) {
motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
@@ -1648,13 +1939,16 @@
motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
}
+ float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
+ float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
+
if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
&& (deltaX != 0.0f || deltaY != 0.0f)) {
// Rotate motion based on display orientation if needed.
// Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
int32_t orientation;
if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
- NULL, NULL, & orientation)) {
+ false /*external*/, NULL, NULL, & orientation)) {
orientation = DISPLAY_ORIENTATION_0;
}
@@ -1667,25 +1961,17 @@
pointerCoords.clear();
- if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
- vscroll = mAccumulator.relWheel;
- } else {
- vscroll = 0;
- }
- mWheelYVelocityControl.move(when, NULL, &vscroll);
+ vscroll = mCursorMotionAccumulator.getRelativeVWheel();
+ hscroll = mCursorMotionAccumulator.getRelativeHWheel();
- if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
- hscroll = mAccumulator.relHWheel;
- } else {
- hscroll = 0;
- }
+ mWheelYVelocityControl.move(when, NULL, &vscroll);
mWheelXVelocityControl.move(when, &hscroll, NULL);
mPointerVelocityControl.move(when, &deltaX, &deltaY);
if (mPointerController != NULL) {
if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
- || buttonsChanged) {
+ || currentButtonState != lastButtonState) {
mPointerController->setPresentation(
PointerControllerInterface::PRESENTATION_POINTER);
@@ -1693,8 +1979,8 @@
mPointerController->move(deltaX, deltaY);
}
- if (buttonsChanged) {
- mPointerController->setButtonState(mLocked.buttonState);
+ if (currentButtonState != lastButtonState) {
+ mPointerController->setButtonState(currentButtonState);
}
mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
@@ -1755,7 +2041,7 @@
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
policyFlags, lastButtonState, currentButtonState);
- mAccumulator.clear();
+ mCursorMotionAccumulator.clearRelativeAxes();
}
int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
@@ -1881,10 +2167,11 @@
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,
+ "orientation=%d, distance=%d, toolType=%d, isHovering=%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));
+ pointer.orientation, pointer.distance,
+ pointer.toolType, toString(pointer.isHovering));
}
if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
@@ -2026,10 +2313,16 @@
getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
mParameters.orientationAware);
- mParameters.associatedDisplayId = mParameters.orientationAware
+ mParameters.associatedDisplayId = -1;
+ mParameters.associatedDisplayIsExternal = false;
+ if (mParameters.orientationAware
|| mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
- || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
- ? 0 : -1;
+ || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
+ mParameters.associatedDisplayIsExternal =
+ mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
+ && getDevice()->isExternal();
+ mParameters.associatedDisplayId = 0;
+ }
}
void TouchInputMapper::dumpParameters(String8& dump) {
@@ -2111,6 +2404,7 @@
if (mParameters.associatedDisplayId >= 0) {
// Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+ mParameters.associatedDisplayIsExternal,
&mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
&mLocked.associatedDisplayOrientation)) {
return false;
@@ -2924,6 +3218,7 @@
calculatePointerIds();
}
+ // Handle initial down events.
uint32_t policyFlags = 0;
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
@@ -3420,7 +3715,7 @@
PointerProperties& properties = mCurrentTouchProperties[i];
properties.clear();
properties.id = mCurrentTouch.pointers[i].id;
- properties.toolType = getTouchToolType(mCurrentTouch.pointers[i].isStylus);
+ properties.toolType = mCurrentTouch.pointers[i].toolType;
}
*outXPrecision = mLocked.orientedXPrecision;
@@ -3604,7 +3899,7 @@
PointerProperties pointerProperties;
pointerProperties.clear();
pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
PointerCoords pointerCoords;
pointerCoords.clear();
@@ -3838,8 +4133,7 @@
mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -3880,7 +4174,7 @@
mPointerGesture.currentGestureProperties[0].id =
mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(
AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
@@ -3993,7 +4287,7 @@
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
@@ -4240,7 +4534,7 @@
mPointerGesture.currentGestureProperties[0].clear();
mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[0].clear();
mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
mPointerGesture.referenceGestureX);
@@ -4331,7 +4625,7 @@
mPointerGesture.currentGestureProperties[i].clear();
mPointerGesture.currentGestureProperties[i].id = gestureId;
mPointerGesture.currentGestureProperties[i].toolType =
- AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
+ AMOTION_EVENT_TOOL_TYPE_FINGER;
mPointerGesture.currentGestureCoords[i].clear();
mPointerGesture.currentGestureCoords[i].setAxisValue(
AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
@@ -4473,15 +4767,6 @@
} // release lock
}
-int32_t TouchInputMapper::getTouchToolType(bool isStylus) const {
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
- return isStylus ? AMOTION_EVENT_TOOL_TYPE_STYLUS : AMOTION_EVENT_TOOL_TYPE_FINGER;
- } else {
- return isStylus ? AMOTION_EVENT_TOOL_TYPE_INDIRECT_STYLUS
- : AMOTION_EVENT_TOOL_TYPE_INDIRECT_FINGER;
- }
-}
-
bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
&& y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
@@ -4760,14 +5045,9 @@
}
void SingleTouchInputMapper::clearState() {
- mAccumulator.clear();
-
- mDown = false;
- mX = 0;
- mY = 0;
- mPressure = 0; // default to 0 for devices that don't report pressure
- mToolWidth = 0; // default to 0 for devices that don't report tool width
- mButtonState = 0;
+ mCursorButtonAccumulator.clearButtons();
+ mTouchButtonAccumulator.clearButtons();
+ mSingleTouchMotionAccumulator.clearAbsoluteAxes();
}
void SingleTouchInputMapper::reset() {
@@ -4777,144 +5057,79 @@
}
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY:
- switch (rawEvent->scanCode) {
- case BTN_TOUCH:
- mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
- mAccumulator.btnTouch = rawEvent->value != 0;
- // Don't sync immediately. Wait until the next SYN_REPORT since we might
- // not have received valid position information yet. This logic assumes that
- // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
- break;
- default:
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown |= buttonState;
- } else {
- mAccumulator.buttonUp |= buttonState;
- }
- mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
- }
- }
- break;
- }
- break;
+ mCursorButtonAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+ mSingleTouchMotionAccumulator.process(rawEvent);
- case EV_ABS:
- switch (rawEvent->scanCode) {
- case ABS_X:
- mAccumulator.fields |= Accumulator::FIELD_ABS_X;
- mAccumulator.absX = rawEvent->value;
- break;
- case ABS_Y:
- mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
- mAccumulator.absY = rawEvent->value;
- break;
- case ABS_PRESSURE:
- mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
- mAccumulator.absPressure = rawEvent->value;
- break;
- case ABS_TOOL_WIDTH:
- mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
- mAccumulator.absToolWidth = rawEvent->value;
- break;
- }
- break;
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void SingleTouchInputMapper::sync(nsecs_t when) {
- uint32_t fields = mAccumulator.fields;
- if (fields == 0) {
- return; // no new state changes, so nothing to do
- }
-
- if (fields & Accumulator::FIELD_BTN_TOUCH) {
- mDown = mAccumulator.btnTouch;
- }
-
- if (fields & Accumulator::FIELD_ABS_X) {
- mX = mAccumulator.absX;
- }
-
- if (fields & Accumulator::FIELD_ABS_Y) {
- mY = mAccumulator.absY;
- }
-
- if (fields & Accumulator::FIELD_ABS_PRESSURE) {
- mPressure = mAccumulator.absPressure;
- }
-
- if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
- mToolWidth = mAccumulator.absToolWidth;
- }
-
- if (fields & Accumulator::FIELD_BUTTONS) {
- mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
- }
-
mCurrentTouch.clear();
- if (mDown) {
+ if (mTouchButtonAccumulator.isActive()) {
+ uint32_t buttonState = mTouchButtonAccumulator.getButtonState();
+ bool isHovering = mTouchButtonAccumulator.isHovering();
+ if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) {
+ isHovering = true;
+ }
+
mCurrentTouch.pointerCount = 1;
- mCurrentTouch.pointers[0].id = 0;
- mCurrentTouch.pointers[0].x = mX;
- mCurrentTouch.pointers[0].y = mY;
- mCurrentTouch.pointers[0].pressure = mPressure;
- mCurrentTouch.pointers[0].touchMajor = 0;
- mCurrentTouch.pointers[0].touchMinor = 0;
- mCurrentTouch.pointers[0].toolMajor = mToolWidth;
- mCurrentTouch.pointers[0].toolMinor = mToolWidth;
- mCurrentTouch.pointers[0].orientation = 0;
- mCurrentTouch.pointers[0].distance = 0;
- mCurrentTouch.pointers[0].isStylus = false; // TODO: Set stylus
mCurrentTouch.idToIndex[0] = 0;
mCurrentTouch.idBits.markBit(0);
- mCurrentTouch.buttonState = mButtonState;
+ mCurrentTouch.buttonState = buttonState;
+
+ PointerData& outPointer = mCurrentTouch.pointers[0];
+ outPointer.id = 0;
+ outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
+ outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
+ outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
+ outPointer.touchMajor = 0;
+ outPointer.touchMinor = 0;
+ outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
+ outPointer.orientation = 0;
+ outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ }
+ outPointer.isHovering = isHovering;
}
syncTouch(when, true);
-
- mAccumulator.clear();
}
void SingleTouchInputMapper::configureRawAxes() {
TouchInputMapper::configureRawAxes();
+ mTouchButtonAccumulator.configure(getDevice());
+
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
+ getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance);
}
// --- MultiTouchInputMapper ---
MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device), mSlotCount(0), mUsingSlotsProtocol(false) {
+ TouchInputMapper(device) {
}
MultiTouchInputMapper::~MultiTouchInputMapper() {
}
void MultiTouchInputMapper::clearState() {
- mAccumulator.clearSlots(mSlotCount);
- mAccumulator.clearButtons();
- mButtonState = 0;
+ mCursorButtonAccumulator.clearButtons();
+ mTouchButtonAccumulator.clearButtons();
mPointerIdBits.clear();
- if (mUsingSlotsProtocol) {
+ if (mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
// Query the driver for the current slot index and use it as the initial slot
// before we start reading events from the device. It is possible that the
// current slot index will not be the same as it was when the first event was
@@ -4924,12 +5139,16 @@
// two slots will be confused until the next ABS_MT_SLOT event is received.
// This can cause the touch point to "jump", but at least there will be
// no stuck touches.
+ int32_t initialSlot;
status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
- &mAccumulator.currentSlot);
+ &initialSlot);
if (status) {
LOGW("Could not retrieve current multitouch slot index. status=%d", status);
- mAccumulator.currentSlot = -1;
+ initialSlot = -1;
}
+ mMultiTouchMotionAccumulator.clearSlots(initialSlot);
+ } else {
+ mMultiTouchMotionAccumulator.clearSlots(-1);
}
}
@@ -4940,124 +5159,26 @@
}
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- int32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
- if (buttonState) {
- if (rawEvent->value) {
- mAccumulator.buttonDown |= buttonState;
- } else {
- mAccumulator.buttonUp |= buttonState;
- }
- }
- }
- break;
- }
+ mCursorButtonAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+ mMultiTouchMotionAccumulator.process(rawEvent);
- case EV_ABS: {
- bool newSlot = false;
- if (mUsingSlotsProtocol && rawEvent->scanCode == ABS_MT_SLOT) {
- mAccumulator.currentSlot = rawEvent->value;
- newSlot = true;
- }
-
- if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
- if (newSlot) {
- LOGW("MultiTouch device %s emitted invalid slot index %d but it "
- "should be between 0 and %d; ignoring this slot.",
- getDeviceName().string(), mAccumulator.currentSlot, mSlotCount);
- }
-#endif
- break;
- }
-
- Accumulator::Slot* slot = &mAccumulator.slots[mAccumulator.currentSlot];
-
- switch (rawEvent->scanCode) {
- case ABS_MT_POSITION_X:
- slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
- slot->absMTPositionX = rawEvent->value;
- break;
- case ABS_MT_POSITION_Y:
- slot->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
- slot->absMTPositionY = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
- slot->absMTTouchMajor = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
- slot->absMTTouchMinor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MAJOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
- slot->absMTWidthMajor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- slot->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
- slot->absMTWidthMinor = rawEvent->value;
- break;
- case ABS_MT_ORIENTATION:
- slot->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
- slot->absMTOrientation = rawEvent->value;
- break;
- case ABS_MT_TRACKING_ID:
- if (mUsingSlotsProtocol && rawEvent->value < 0) {
- slot->clear();
- } else {
- slot->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
- slot->absMTTrackingId = rawEvent->value;
- }
- break;
- case ABS_MT_PRESSURE:
- slot->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
- slot->absMTPressure = rawEvent->value;
- break;
- case ABS_MT_TOOL_TYPE:
- slot->fields |= Accumulator::FIELD_ABS_MT_TOOL_TYPE;
- slot->absMTToolType = rawEvent->value;
- break;
- }
- break;
- }
-
- case EV_SYN:
- switch (rawEvent->scanCode) {
- case SYN_MT_REPORT: {
- // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
- mAccumulator.currentSlot += 1;
- break;
- }
-
- case SYN_REPORT:
- sync(rawEvent->when);
- break;
- }
- break;
+ if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
+ sync(rawEvent->when);
}
}
void MultiTouchInputMapper::sync(nsecs_t when) {
- static const uint32_t REQUIRED_FIELDS =
- Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
- size_t inCount = mSlotCount;
+ size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
size_t outCount = 0;
bool havePointerIds = true;
mCurrentTouch.clear();
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const Accumulator::Slot& inSlot = mAccumulator.slots[inIndex];
- uint32_t fields = inSlot.fields;
-
- if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
- // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
- // This may also indicate an unused slot.
- // Drop this finger.
+ const MultiTouchMotionAccumulator::Slot* inSlot =
+ mMultiTouchMotionAccumulator.getSlot(inIndex);
+ if (!inSlot->isInUse()) {
continue;
}
@@ -5071,76 +5192,32 @@
}
PointerData& outPointer = mCurrentTouch.pointers[outCount];
- outPointer.x = inSlot.absMTPositionX;
- outPointer.y = inSlot.absMTPositionY;
+ outPointer.x = inSlot->getX();
+ outPointer.y = inSlot->getY();
+ outPointer.pressure = inSlot->getPressure();
+ outPointer.touchMajor = inSlot->getTouchMajor();
+ outPointer.touchMinor = inSlot->getTouchMinor();
+ outPointer.toolMajor = inSlot->getToolMajor();
+ outPointer.toolMinor = inSlot->getToolMinor();
+ outPointer.orientation = inSlot->getOrientation();
+ outPointer.distance = inSlot->getDistance();
- if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
- outPointer.pressure = inSlot.absMTPressure;
- } else {
- // Default pressure to 0 if absent.
- outPointer.pressure = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
- if (inSlot.absMTTouchMajor <= 0) {
- // Some devices send sync packets with X / Y but with a 0 touch major to indicate
- // a pointer going up. Drop this finger.
- continue;
+ outPointer.toolType = inSlot->getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = mTouchButtonAccumulator.getToolType();
+ if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
+ outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
}
- outPointer.touchMajor = inSlot.absMTTouchMajor;
- } else {
- // Default touch area to 0 if absent.
- outPointer.touchMajor = 0;
}
- if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
- outPointer.touchMinor = inSlot.absMTTouchMinor;
- } else {
- // Assume touch area is circular.
- outPointer.touchMinor = outPointer.touchMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
- outPointer.toolMajor = inSlot.absMTWidthMajor;
- } else {
- // Default tool area to 0 if absent.
- outPointer.toolMajor = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
- outPointer.toolMinor = inSlot.absMTWidthMinor;
- } else {
- // Assume tool area is circular.
- outPointer.toolMinor = outPointer.toolMajor;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
- outPointer.orientation = inSlot.absMTOrientation;
- } else {
- // Default orientation to vertical if absent.
- outPointer.orientation = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_DISTANCE) {
- outPointer.distance = inSlot.absMTDistance;
- } else {
- // Default distance is 0 (direct contact).
- outPointer.distance = 0;
- }
-
- if (fields & Accumulator::FIELD_ABS_MT_TOOL_TYPE) {
- outPointer.isStylus = (inSlot.absMTToolType == MT_TOOL_PEN);
- } else {
- // Assume this is not a stylus.
- outPointer.isStylus = false;
- }
+ outPointer.isHovering = mTouchButtonAccumulator.isHovering()
+ || inSlot->getDistance() > 0;
// Assign pointer id using tracking id if available.
if (havePointerIds) {
+ int32_t trackingId = inSlot->getTrackingId();
int32_t id = -1;
- if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
- int32_t trackingId = inSlot.absMTTrackingId;
-
+ if (trackingId >= 0) {
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
uint32_t n = idBits.firstMarkedBit();
idBits.clearBit(n);
@@ -5170,23 +5247,22 @@
}
mCurrentTouch.pointerCount = outCount;
-
- mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
- mCurrentTouch.buttonState = mButtonState;
+ mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState();
mPointerIdBits = mCurrentTouch.idBits;
syncTouch(when, havePointerIds);
- if (!mUsingSlotsProtocol) {
- mAccumulator.clearSlots(mSlotCount);
+ if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
+ mMultiTouchMotionAccumulator.clearSlots(-1);
}
- mAccumulator.clearButtons();
}
void MultiTouchInputMapper::configureRawAxes() {
TouchInputMapper::configureRawAxes();
+ mTouchButtonAccumulator.configure(getDevice());
+
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y);
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor);
@@ -5201,21 +5277,18 @@
if (mRawAxes.trackingId.valid
&& mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) {
- mSlotCount = mRawAxes.slot.maxValue + 1;
- if (mSlotCount > MAX_SLOTS) {
+ size_t slotCount = mRawAxes.slot.maxValue + 1;
+ if (slotCount > MAX_SLOTS) {
LOGW("MultiTouch Device %s reported %d slots but the framework "
"only supports a maximum of %d slots at this time.",
- getDeviceName().string(), mSlotCount, MAX_SLOTS);
- mSlotCount = MAX_SLOTS;
+ getDeviceName().string(), slotCount, MAX_SLOTS);
+ slotCount = MAX_SLOTS;
}
- mUsingSlotsProtocol = true;
+ mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
} else {
- mSlotCount = MAX_POINTERS;
- mUsingSlotsProtocol = false;
+ mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
}
- mAccumulator.allocateSlots(mSlotCount);
-
clearState();
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index b1fdcf2..ee6990b 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -180,9 +180,11 @@
};
/* Gets information about the display with the specified id.
+ * If external is true, returns the size of the external mirrored
+ * counterpart of the specified display.
* Returns true if the display info is available, false otherwise.
*/
- virtual bool getDisplayInfo(int32_t displayId,
+ virtual bool getDisplayInfo(int32_t displayId, bool external,
int32_t* width, int32_t* height, int32_t* orientation) = 0;
/* Gets the input reader configuration. */
@@ -430,9 +432,8 @@
void fadePointer();
- inline const PropertyMap& getConfiguration() {
- return mConfiguration;
- }
+ inline const PropertyMap& getConfiguration() { return mConfiguration; }
+ inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
private:
InputReaderContext* mContext;
@@ -452,6 +453,171 @@
};
+/* Keeps track of the state of mouse or touch pad buttons. */
+class CursorButtonAccumulator {
+public:
+ CursorButtonAccumulator();
+
+ void clearButtons();
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+
+private:
+ bool mBtnLeft;
+ bool mBtnRight;
+ bool mBtnMiddle;
+ bool mBtnBack;
+ bool mBtnSide;
+ bool mBtnForward;
+ bool mBtnExtra;
+ bool mBtnTask;
+};
+
+
+/* Keeps track of cursor movements. */
+
+class CursorMotionAccumulator {
+public:
+ CursorMotionAccumulator();
+ void configure(InputDevice* device);
+
+ void clearRelativeAxes();
+ void process(const RawEvent* rawEvent);
+
+ inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
+ inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
+
+ inline int32_t getRelativeX() const { return mRelX; }
+ inline int32_t getRelativeY() const { return mRelY; }
+ inline int32_t getRelativeVWheel() const { return mRelWheel; }
+ inline int32_t getRelativeHWheel() const { return mRelHWheel; }
+
+private:
+ bool mHaveRelWheel;
+ bool mHaveRelHWheel;
+
+ int32_t mRelX;
+ int32_t mRelY;
+ int32_t mRelWheel;
+ int32_t mRelHWheel;
+};
+
+
+/* Keeps track of the state of touch, stylus and tool buttons. */
+class TouchButtonAccumulator {
+public:
+ TouchButtonAccumulator();
+ void configure(InputDevice* device);
+
+ void clearButtons();
+ void process(const RawEvent* rawEvent);
+
+ uint32_t getButtonState() const;
+ int32_t getToolType() const;
+ bool isActive() const;
+ bool isHovering() const;
+
+private:
+ bool mHaveBtnTouch;
+
+ bool mBtnTouch;
+ bool mBtnStylus;
+ bool mBtnStylus2;
+ bool mBtnToolFinger;
+ bool mBtnToolPen;
+ bool mBtnToolRubber;
+};
+
+
+/* Keeps track of the state of single-touch protocol. */
+class SingleTouchMotionAccumulator {
+public:
+ SingleTouchMotionAccumulator();
+
+ void clearAbsoluteAxes();
+ void process(const RawEvent* rawEvent);
+
+ inline int32_t getAbsoluteX() const { return mAbsX; }
+ inline int32_t getAbsoluteY() const { return mAbsY; }
+ inline int32_t getAbsolutePressure() const { return mAbsPressure; }
+ inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
+ inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
+
+private:
+ int32_t mAbsX;
+ int32_t mAbsY;
+ int32_t mAbsPressure;
+ int32_t mAbsToolWidth;
+ int32_t mAbsDistance;
+};
+
+
+/* Keeps track of the state of multi-touch protocol. */
+class MultiTouchMotionAccumulator {
+public:
+ class Slot {
+ public:
+ inline bool isInUse() const { return mInUse; }
+ inline int32_t getX() const { return mAbsMTPositionX; }
+ inline int32_t getY() const { return mAbsMTPositionY; }
+ inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
+ inline int32_t getTouchMinor() const {
+ return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
+ inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
+ inline int32_t getToolMinor() const {
+ return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
+ inline int32_t getOrientation() const { return mAbsMTOrientation; }
+ inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
+ inline int32_t getPressure() const { return mAbsMTPressure; }
+ inline int32_t getDistance() const { return mAbsMTDistance; }
+ inline int32_t getToolType() const;
+
+ private:
+ friend class MultiTouchMotionAccumulator;
+
+ bool mInUse;
+ bool mHaveAbsMTTouchMinor;
+ bool mHaveAbsMTWidthMinor;
+ bool mHaveAbsMTToolType;
+
+ int32_t mAbsMTPositionX;
+ int32_t mAbsMTPositionY;
+ int32_t mAbsMTTouchMajor;
+ int32_t mAbsMTTouchMinor;
+ int32_t mAbsMTWidthMajor;
+ int32_t mAbsMTWidthMinor;
+ int32_t mAbsMTOrientation;
+ int32_t mAbsMTTrackingId;
+ int32_t mAbsMTPressure;
+ int32_t mAbsMTToolType;
+ int32_t mAbsMTDistance;
+
+ Slot();
+ void clearIfInUse();
+ void clear();
+ };
+
+ MultiTouchMotionAccumulator();
+ ~MultiTouchMotionAccumulator();
+
+ void configure(size_t slotCount, bool usingSlotsProtocol);
+ void process(const RawEvent* rawEvent);
+
+ void clearSlots(int32_t initialSlot);
+
+ inline bool isUsingSlotsProtocol() const { return mUsingSlotsProtocol; }
+ inline size_t getSlotCount() const { return mSlotCount; }
+ inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+
+private:
+ int32_t mCurrentSlot;
+ Slot* mSlots;
+ size_t mSlotCount;
+ bool mUsingSlotsProtocol;
+};
+
+
/* An input mapper transforms raw input events into cooked event data.
* A single input device can have multiple associated input mappers in order to interpret
* different classes of events.
@@ -615,29 +781,8 @@
bool orientationAware;
} mParameters;
- struct Accumulator {
- enum {
- FIELD_BUTTONS = 1,
- FIELD_REL_X = 2,
- FIELD_REL_Y = 4,
- FIELD_REL_WHEEL = 8,
- FIELD_REL_HWHEEL = 16,
- };
-
- uint32_t fields;
-
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- int32_t relX;
- int32_t relY;
- int32_t relWheel;
- int32_t relHWheel;
-
- inline void clear() {
- fields = 0;
- }
- } mAccumulator;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ CursorMotionAccumulator mCursorMotionAccumulator;
int32_t mSource;
float mXScale;
@@ -645,8 +790,6 @@
float mXPrecision;
float mYPrecision;
- bool mHaveVWheel;
- bool mHaveHWheel;
float mVWheelScale;
float mHWheelScale;
@@ -722,7 +865,8 @@
int32_t toolMinor;
int32_t orientation;
int32_t distance;
- bool isStylus;
+ int32_t toolType; // AMOTION_EVENT_TOOL_TYPE constant
+ bool isHovering;
inline bool operator== (const PointerData& other) const {
return id == other.id
@@ -734,7 +878,9 @@
&& toolMajor == other.toolMajor
&& toolMinor == other.toolMinor
&& orientation == other.orientation
- && distance == other.distance;
+ && distance == other.distance
+ && toolType == other.toolType
+ && isHovering == other.isHovering;
}
inline bool operator!= (const PointerData& other) const {
return !(*this == other);
@@ -800,6 +946,7 @@
DeviceType deviceType;
int32_t associatedDisplayId;
+ bool associatedDisplayIsExternal;
bool orientationAware;
enum GestureMode {
@@ -1201,7 +1348,6 @@
void suppressSwipeOntoVirtualKeys(nsecs_t when);
- int32_t getTouchToolType(bool isStylus) const;
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
@@ -1221,40 +1367,9 @@
virtual void configureRawAxes();
private:
- struct Accumulator {
- enum {
- FIELD_BTN_TOUCH = 1,
- FIELD_ABS_X = 2,
- FIELD_ABS_Y = 4,
- FIELD_ABS_PRESSURE = 8,
- FIELD_ABS_TOOL_WIDTH = 16,
- FIELD_BUTTONS = 32,
- };
-
- uint32_t fields;
-
- bool btnTouch;
- int32_t absX;
- int32_t absY;
- int32_t absPressure;
- int32_t absToolWidth;
-
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- inline void clear() {
- fields = 0;
- buttonDown = 0;
- buttonUp = 0;
- }
- } mAccumulator;
-
- bool mDown;
- int32_t mX;
- int32_t mY;
- int32_t mPressure;
- int32_t mToolWidth;
- int32_t mButtonState;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+ SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
void clearState();
@@ -1274,83 +1389,9 @@
virtual void configureRawAxes();
private:
- struct Accumulator {
- enum {
- FIELD_ABS_MT_POSITION_X = 1 << 0,
- FIELD_ABS_MT_POSITION_Y = 1 << 1,
- FIELD_ABS_MT_TOUCH_MAJOR = 1 << 2,
- FIELD_ABS_MT_TOUCH_MINOR = 1 << 3,
- FIELD_ABS_MT_WIDTH_MAJOR = 1 << 4,
- FIELD_ABS_MT_WIDTH_MINOR = 1 << 5,
- FIELD_ABS_MT_ORIENTATION = 1 << 6,
- FIELD_ABS_MT_TRACKING_ID = 1 << 7,
- FIELD_ABS_MT_PRESSURE = 1 << 8,
- FIELD_ABS_MT_TOOL_TYPE = 1 << 9,
- FIELD_ABS_MT_DISTANCE = 1 << 10,
- };
-
- struct Slot {
- uint32_t fields; // 0 if slot is unused
-
- int32_t absMTPositionX;
- int32_t absMTPositionY;
- int32_t absMTTouchMajor;
- int32_t absMTTouchMinor;
- int32_t absMTWidthMajor;
- int32_t absMTWidthMinor;
- int32_t absMTOrientation;
- int32_t absMTTrackingId;
- int32_t absMTPressure;
- int32_t absMTToolType;
- int32_t absMTDistance;
-
- inline Slot() {
- clear();
- }
-
- inline void clear() {
- fields = 0;
- }
- };
-
- // Current slot index.
- int32_t currentSlot;
-
- // Array of slots.
- Slot* slots;
-
- // Bitfield of buttons that went down or up.
- uint32_t buttonDown;
- uint32_t buttonUp;
-
- Accumulator() : currentSlot(0), slots(NULL), buttonDown(0), buttonUp(0) {
- }
-
- ~Accumulator() {
- delete[] slots;
- }
-
- void allocateSlots(size_t slotCount) {
- slots = new Slot[slotCount];
- }
-
- void clearSlots(size_t slotCount) {
- for (size_t i = 0; i < slotCount; i++) {
- slots[i].clear();
- }
- currentSlot = 0;
- }
-
- void clearButtons() {
- buttonDown = 0;
- buttonUp = 0;
- }
- } mAccumulator;
-
- size_t mSlotCount;
- bool mUsingSlotsProtocol;
-
- int32_t mButtonState;
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+ MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
// Specifies the pointer id bits that are in use, and their associated tracking id.
BitSet32 mPointerIdBits;
diff --git a/services/input/tests/Android.mk b/services/input/tests/Android.mk
index d92fc74..171db3c 100644
--- a/services/input/tests/Android.mk
+++ b/services/input/tests/Android.mk
@@ -42,4 +42,4 @@
)
# Build the manual test programs.
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 131894a..8533743 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -157,7 +157,7 @@
}
private:
- virtual bool getDisplayInfo(int32_t displayId,
+ virtual bool getDisplayInfo(int32_t displayId, bool external /*currently ignored*/,
int32_t* width, int32_t* height, int32_t* orientation) {
ssize_t index = mDisplayInfos.indexOfKey(displayId);
if (index >= 0) {
@@ -707,6 +707,15 @@
return result;
}
+ virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->keys.indexOfKey(scanCode);
+ return index >= 0;
+ }
+ return false;
+ }
+
virtual bool hasLed(int32_t deviceId, int32_t led) const {
Device* device = getDevice(deviceId);
return device && device->leds.indexOfKey(led) >= 0;
@@ -2116,6 +2125,7 @@
// Button press.
// Mostly testing non x/y behavior here so we don't need to check again elsewhere.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2137,6 +2147,7 @@
// Button release. Should have same down time.
process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
ASSERT_EQ(DEVICE_ID, args.deviceId);
@@ -2190,6 +2201,7 @@
// Button press without following sync.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2197,6 +2209,7 @@
// Button release without following sync.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2233,6 +2246,7 @@
// Release Button.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
@@ -2248,10 +2262,12 @@
// Button press.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Button release.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Reset. Should not synthesize button up since button is not pressed.
@@ -2269,6 +2285,7 @@
// Button press.
process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
// Reset. Should synthesize button up.
@@ -2445,6 +2462,7 @@
class SingleTouchInputMapperTest : public TouchInputMapperTest {
protected:
+ void prepareButtons();
void prepareAxes(int axes);
void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
@@ -2455,6 +2473,10 @@
void processSync(SingleTouchInputMapper* mapper);
};
+void SingleTouchInputMapperTest::prepareButtons() {
+ mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0);
+}
+
void SingleTouchInputMapperTest::prepareAxes(int axes) {
if (axes & POSITION) {
mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X,
@@ -2504,6 +2526,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -2514,6 +2537,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -2522,6 +2546,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchPad");
addMapperAndConfigure(mapper);
@@ -2531,6 +2556,7 @@
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
addMapperAndConfigure(mapper);
@@ -2542,6 +2568,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2570,6 +2597,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2598,6 +2626,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2615,6 +2644,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2649,6 +2679,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2676,6 +2707,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2726,6 +2758,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2847,6 +2880,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -2920,6 +2954,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
addMapperAndConfigure(mapper);
@@ -3009,6 +3044,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareButtons();
prepareAxes(POSITION);
addConfigurationProperty("touch.orientationAware", "0");
addMapperAndConfigure(mapper);
@@ -3032,6 +3068,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareButtons();
prepareAxes(POSITION);
addMapperAndConfigure(mapper);
@@ -3094,6 +3131,7 @@
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
prepareAxes(POSITION | PRESSURE | TOOL);
addMapperAndConfigure(mapper);
@@ -3815,6 +3853,7 @@
FakeInputDispatcher::NotifyMotionArgs args;
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+
ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
args.action);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index e9e66cb..3ec2a96 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -76,7 +76,11 @@
import com.android.internal.backup.LocalTransport;
import com.android.server.PackageManagerBackupAgent.Metadata;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileDescriptor;
@@ -85,9 +89,16 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
-import java.io.UnsupportedEncodingException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -101,9 +112,20 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
class BackupManagerService extends IBackupManager.Stub {
private static final String TAG = "BackupManagerService";
private static final boolean DEBUG = true;
@@ -113,6 +135,7 @@
static final int BACKUP_MANIFEST_VERSION = 1;
static final String BACKUP_FILE_HEADER_MAGIC = "ANDROID BACKUP\n";
static final int BACKUP_FILE_VERSION = 1;
+ static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production
// How often we perform a backup pass. Privileged external callers can
// trigger an immediate pass.
@@ -148,8 +171,9 @@
static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000;
static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000;
- // User confirmation timeout for a full backup/restore operation
- static final long TIMEOUT_FULL_CONFIRMATION = 30 * 1000;
+ // User confirmation timeout for a full backup/restore operation. It's this long in
+ // order to give them time to enter the backup password.
+ static final long TIMEOUT_FULL_CONFIRMATION = 60 * 1000;
private Context mContext;
private PackageManager mPackageManager;
@@ -283,6 +307,7 @@
public ParcelFileDescriptor fd;
public final AtomicBoolean latch;
public IFullBackupRestoreObserver observer;
+ public String password; // filled in by the confirmation step
FullParams() {
latch = new AtomicBoolean(false);
@@ -329,6 +354,23 @@
File mJournalDir;
File mJournal;
+ // Backup password, if any, and the file where it's saved. What is stored is not the
+ // password text itself; it's the result of a PBKDF2 hash with a randomly chosen (but
+ // persisted) salt. Validation is performed by running the challenge text through the
+ // same PBKDF2 cycle with the persisted salt; if the resulting derived key string matches
+ // the saved hash string, then the challenge text matches the originally supplied
+ // password text.
+ private final SecureRandom mRng = new SecureRandom();
+ private String mPasswordHash;
+ private File mPasswordHashFile;
+ private byte[] mPasswordSalt;
+
+ // Configuration of PBKDF2 that we use for generating pw hashes and intermediate keys
+ static final int PBKDF2_HASH_ROUNDS = 10000;
+ static final int PBKDF2_KEY_SIZE = 256; // bits
+ static final int PBKDF2_SALT_SIZE = 512; // bits
+ static final String ENCRYPTION_ALGORITHM_NAME = "AES-256";
+
// Keep a log of all the apps we've ever backed up, and what the
// dataset tokens are for both the current backup dataset and
// the ancestral dataset.
@@ -416,7 +458,7 @@
{
FullBackupParams params = (FullBackupParams)msg.obj;
(new PerformFullBackupTask(params.fd, params.observer, params.includeApks,
- params.includeShared, params.allApps, params.packages,
+ params.includeShared, params.password, params.allApps, params.packages,
params.latch)).run();
break;
}
@@ -434,7 +476,8 @@
case MSG_RUN_FULL_RESTORE:
{
FullRestoreParams params = (FullRestoreParams)msg.obj;
- (new PerformFullRestoreTask(params.fd, params.observer, params.latch)).run();
+ (new PerformFullRestoreTask(params.fd, params.password,
+ params.observer, params.latch)).run();
break;
}
@@ -584,6 +627,32 @@
mBaseStateDir.mkdirs();
mDataDir = Environment.getDownloadCacheDirectory();
+ mPasswordHashFile = new File(mBaseStateDir, "pwhash");
+ if (mPasswordHashFile.exists()) {
+ FileInputStream fin = null;
+ DataInputStream in = null;
+ try {
+ fin = new FileInputStream(mPasswordHashFile);
+ in = new DataInputStream(new BufferedInputStream(fin));
+ // integer length of the salt array, followed by the salt,
+ // then the hex pw hash string
+ int saltLen = in.readInt();
+ byte[] salt = new byte[saltLen];
+ in.readFully(salt);
+ mPasswordHash = in.readUTF();
+ mPasswordSalt = salt;
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to read saved backup pw hash");
+ } finally {
+ try {
+ if (in != null) in.close();
+ if (fin != null) fin.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to close streams");
+ }
+ }
+ }
+
// Alarm receivers for scheduled backups & initialization operations
mRunBackupReceiver = new RunBackupReceiver();
IntentFilter filter = new IntentFilter();
@@ -843,6 +912,151 @@
}
}
+ private SecretKey buildPasswordKey(String pw, byte[] salt, int rounds) {
+ return buildCharArrayKey(pw.toCharArray(), salt, rounds);
+ }
+
+ private SecretKey buildCharArrayKey(char[] pwArray, byte[] salt, int rounds) {
+ try {
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+ KeySpec ks = new PBEKeySpec(pwArray, salt, rounds, PBKDF2_KEY_SIZE);
+ return keyFactory.generateSecret(ks);
+ } catch (InvalidKeySpecException e) {
+ Slog.e(TAG, "Invalid key spec for PBKDF2!");
+ } catch (NoSuchAlgorithmException e) {
+ Slog.e(TAG, "PBKDF2 unavailable!");
+ }
+ return null;
+ }
+
+ private String buildPasswordHash(String pw, byte[] salt, int rounds) {
+ SecretKey key = buildPasswordKey(pw, salt, rounds);
+ if (key != null) {
+ return byteArrayToHex(key.getEncoded());
+ }
+ return null;
+ }
+
+ private String byteArrayToHex(byte[] data) {
+ StringBuilder buf = new StringBuilder(data.length * 2);
+ for (int i = 0; i < data.length; i++) {
+ buf.append(Byte.toHexString(data[i], true));
+ }
+ return buf.toString();
+ }
+
+ private byte[] hexToByteArray(String digits) {
+ final int bytes = digits.length() / 2;
+ if (2*bytes != digits.length()) {
+ throw new IllegalArgumentException("Hex string must have an even number of digits");
+ }
+
+ byte[] result = new byte[bytes];
+ for (int i = 0; i < digits.length(); i += 2) {
+ result[i/2] = (byte) Integer.parseInt(digits.substring(i, i+2), 16);
+ }
+ return result;
+ }
+
+ private byte[] makeKeyChecksum(byte[] pwBytes, byte[] salt, int rounds) {
+ char[] mkAsChar = new char[pwBytes.length];
+ for (int i = 0; i < pwBytes.length; i++) {
+ mkAsChar[i] = (char) pwBytes[i];
+ }
+
+ Key checksum = buildCharArrayKey(mkAsChar, salt, rounds);
+ return checksum.getEncoded();
+ }
+
+ // Used for generating random salts or passwords
+ private byte[] randomBytes(int bits) {
+ byte[] array = new byte[bits / 8];
+ mRng.nextBytes(array);
+ return array;
+ }
+
+ // Backup password management
+ boolean passwordMatchesSaved(String candidatePw, int rounds) {
+ if (mPasswordHash == null) {
+ // no current password case -- require that 'currentPw' be null or empty
+ if (candidatePw == null || "".equals(candidatePw)) {
+ return true;
+ } // else the non-empty candidate does not match the empty stored pw
+ } else {
+ // hash the stated current pw and compare to the stored one
+ if (candidatePw != null && candidatePw.length() > 0) {
+ String currentPwHash = buildPasswordHash(candidatePw, mPasswordSalt, rounds);
+ if (mPasswordHash.equalsIgnoreCase(currentPwHash)) {
+ // candidate hash matches the stored hash -- the password matches
+ return true;
+ }
+ } // else the stored pw is nonempty but the candidate is empty; no match
+ }
+ return false;
+ }
+
+ @Override
+ public boolean setBackupPassword(String currentPw, String newPw) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "setBackupPassword");
+
+ // If the supplied pw doesn't hash to the the saved one, fail
+ if (!passwordMatchesSaved(currentPw, PBKDF2_HASH_ROUNDS)) {
+ return false;
+ }
+
+ // Clearing the password is okay
+ if (newPw == null || newPw.isEmpty()) {
+ if (mPasswordHashFile.exists()) {
+ if (!mPasswordHashFile.delete()) {
+ // Unable to delete the old pw file, so fail
+ Slog.e(TAG, "Unable to clear backup password");
+ return false;
+ }
+ }
+ mPasswordHash = null;
+ mPasswordSalt = null;
+ return true;
+ }
+
+ try {
+ // Okay, build the hash of the new backup password
+ byte[] salt = randomBytes(PBKDF2_SALT_SIZE);
+ String newPwHash = buildPasswordHash(newPw, salt, PBKDF2_HASH_ROUNDS);
+
+ OutputStream pwf = null, buffer = null;
+ DataOutputStream out = null;
+ try {
+ pwf = new FileOutputStream(mPasswordHashFile);
+ buffer = new BufferedOutputStream(pwf);
+ out = new DataOutputStream(buffer);
+ // integer length of the salt array, followed by the salt,
+ // then the hex pw hash string
+ out.writeInt(salt.length);
+ out.write(salt);
+ out.writeUTF(newPwHash);
+ out.flush();
+ mPasswordHash = newPwHash;
+ mPasswordSalt = salt;
+ return true;
+ } finally {
+ if (out != null) out.close();
+ if (buffer != null) buffer.close();
+ if (pwf != null) pwf.close();
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Unable to set backup password");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean hasBackupPassword() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "hasBackupPassword");
+ return (mPasswordHash != null && mPasswordHash.length() > 0);
+ }
+
// Maintain persistent state around whether need to do an initialize operation.
// Must be called with the queue lock held.
void recordInitPendingLocked(boolean isPending, String transportName) {
@@ -1694,6 +1908,7 @@
boolean mIncludeShared;
boolean mAllApps;
String[] mPackages;
+ String mUserPassword;
AtomicBoolean mLatchObject;
File mFilesDir;
File mManifestFile;
@@ -1748,7 +1963,7 @@
}
PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
- boolean includeApks, boolean includeShared,
+ boolean includeApks, boolean includeShared, String password,
boolean doAllApps, String[] packages, AtomicBoolean latch) {
mOutputFile = fd;
mObserver = observer;
@@ -1756,6 +1971,7 @@
mIncludeShared = includeShared;
mAllApps = doAllApps;
mPackages = packages;
+ mUserPassword = password;
mLatchObject = latch;
mFilesDir = new File("/data/system");
@@ -1796,16 +2012,13 @@
}
FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor());
-
- // Set up the compression stage
- Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
- DeflaterOutputStream out = new DeflaterOutputStream(ofstream, deflater, true);
+ OutputStream out = null;
PackageInfo pkg = null;
try {
-
- // !!! TODO: if using encryption, set up the encryption stage
- // and emit the tar header stating the password salt.
+ boolean encrypting = (mUserPassword != null && mUserPassword.length() > 0);
+ boolean compressing = COMPRESS_FULL_BACKUPS;
+ OutputStream finalOutput = ofstream;
// Write the global file header. All strings are UTF-8 encoded; lines end
// with a '\n' byte. Actual backup data begins immediately following the
@@ -1814,17 +2027,57 @@
// line 1: "ANDROID BACKUP"
// line 2: backup file format version, currently "1"
// line 3: compressed? "0" if not compressed, "1" if compressed.
- // line 4: encryption salt? "-" if not encrypted, otherwise this
- // line contains the encryption salt with which the user-
- // supplied password is to be expanded, in hexadecimal.
- StringBuffer headerbuf = new StringBuffer(256);
- // !!! TODO: programmatically build the compressed / encryption salt fields
+ // line 4: name of encryption algorithm [currently only "none" or "AES-256"]
+ //
+ // When line 4 is not "none", then additional header data follows:
+ //
+ // line 5: user password salt [hex]
+ // line 6: master key checksum salt [hex]
+ // line 7: number of PBKDF2 rounds to use (same for user & master) [decimal]
+ // line 8: IV of the user key [hex]
+ // line 9: master key blob [hex]
+ // IV of the master key, master key itself, master key checksum hash
+ //
+ // The master key checksum is the master key plus its checksum salt, run through
+ // 10k rounds of PBKDF2. This is used to verify that the user has supplied the
+ // correct password for decrypting the archive: the master key decrypted from
+ // the archive using the user-supplied password is also run through PBKDF2 in
+ // this way, and if the result does not match the checksum as stored in the
+ // archive, then we know that the user-supplied password does not match the
+ // archive's.
+ StringBuilder headerbuf = new StringBuilder(1024);
+
headerbuf.append(BACKUP_FILE_HEADER_MAGIC);
- headerbuf.append("1\n1\n-\n");
+ headerbuf.append(BACKUP_FILE_VERSION); // integer, no trailing \n
+ headerbuf.append(compressing ? "\n1\n" : "\n0\n");
try {
+ // Set up the encryption stage if appropriate, and emit the correct header
+ if (encrypting) {
+ // Verify that the given password matches the currently-active
+ // backup password, if any
+ if (hasBackupPassword()) {
+ if (!passwordMatchesSaved(mUserPassword, PBKDF2_HASH_ROUNDS)) {
+ if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
+ return;
+ }
+ }
+
+ finalOutput = emitAesBackupHeader(headerbuf, finalOutput);
+ } else {
+ headerbuf.append("none\n");
+ }
+
byte[] header = headerbuf.toString().getBytes("UTF-8");
ofstream.write(header);
+
+ // Set up the compression stage feeding into the encryption stage (if any)
+ if (compressing) {
+ Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+ finalOutput = new DeflaterOutputStream(finalOutput, deflater, true);
+ }
+
+ out = finalOutput;
} catch (Exception e) {
// Should never happen!
Slog.e(TAG, "Unable to emit archive header", e);
@@ -1847,7 +2100,7 @@
} finally {
tearDown(pkg);
try {
- out.close();
+ if (out != null) out.close();
mOutputFile.close();
} catch (IOException e) {
/* nothing we can do about this */
@@ -1865,7 +2118,78 @@
}
}
- private void backupOnePackage(PackageInfo pkg, DeflaterOutputStream out)
+ private OutputStream emitAesBackupHeader(StringBuilder headerbuf,
+ OutputStream ofstream) throws Exception {
+ // User key will be used to encrypt the master key.
+ byte[] newUserSalt = randomBytes(PBKDF2_SALT_SIZE);
+ SecretKey userKey = buildPasswordKey(mUserPassword, newUserSalt,
+ PBKDF2_HASH_ROUNDS);
+
+ // the master key is random for each backup
+ byte[] masterPw = new byte[256 / 8];
+ mRng.nextBytes(masterPw);
+ byte[] checksumSalt = randomBytes(PBKDF2_SALT_SIZE);
+
+ // primary encryption of the datastream with the random key
+ Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ SecretKeySpec masterKeySpec = new SecretKeySpec(masterPw, "AES");
+ c.init(Cipher.ENCRYPT_MODE, masterKeySpec);
+ OutputStream finalOutput = new CipherOutputStream(ofstream, c);
+
+ // line 4: name of encryption algorithm
+ headerbuf.append(ENCRYPTION_ALGORITHM_NAME);
+ headerbuf.append('\n');
+ // line 5: user password salt [hex]
+ headerbuf.append(byteArrayToHex(newUserSalt));
+ headerbuf.append('\n');
+ // line 6: master key checksum salt [hex]
+ headerbuf.append(byteArrayToHex(checksumSalt));
+ headerbuf.append('\n');
+ // line 7: number of PBKDF2 rounds used [decimal]
+ headerbuf.append(PBKDF2_HASH_ROUNDS);
+ headerbuf.append('\n');
+
+ // line 8: IV of the user key [hex]
+ Cipher mkC = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ mkC.init(Cipher.ENCRYPT_MODE, userKey);
+
+ byte[] IV = mkC.getIV();
+ headerbuf.append(byteArrayToHex(IV));
+ headerbuf.append('\n');
+
+ // line 9: master IV + key blob, encrypted by the user key [hex]. Blob format:
+ // [byte] IV length = Niv
+ // [array of Niv bytes] IV itself
+ // [byte] master key length = Nmk
+ // [array of Nmk bytes] master key itself
+ // [byte] MK checksum hash length = Nck
+ // [array of Nck bytes] master key checksum hash
+ //
+ // The checksum is the (master key + checksum salt), run through the
+ // stated number of PBKDF2 rounds
+ IV = c.getIV();
+ byte[] mk = masterKeySpec.getEncoded();
+ byte[] checksum = makeKeyChecksum(masterKeySpec.getEncoded(),
+ checksumSalt, PBKDF2_HASH_ROUNDS);
+
+ ByteArrayOutputStream blob = new ByteArrayOutputStream(IV.length + mk.length
+ + checksum.length + 3);
+ DataOutputStream mkOut = new DataOutputStream(blob);
+ mkOut.writeByte(IV.length);
+ mkOut.write(IV);
+ mkOut.writeByte(mk.length);
+ mkOut.write(mk);
+ mkOut.writeByte(checksum.length);
+ mkOut.write(checksum);
+ mkOut.flush();
+ byte[] encryptedMk = mkC.doFinal(blob.toByteArray());
+ headerbuf.append(byteArrayToHex(encryptedMk));
+ headerbuf.append('\n');
+
+ return finalOutput;
+ }
+
+ private void backupOnePackage(PackageInfo pkg, OutputStream out)
throws RemoteException {
Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
@@ -1922,13 +2246,12 @@
Slog.e(TAG, "Error backing up " + pkg.packageName, e);
} finally {
try {
+ // flush after every package
+ out.flush();
if (pipes != null) {
if (pipes[0] != null) pipes[0].close();
if (pipes[1] != null) pipes[1].close();
}
-
- // Apply a full sync/flush after each application's data
- out.flush();
} catch (IOException e) {
Slog.w(TAG, "Error bringing down backup stack");
}
@@ -2037,7 +2360,8 @@
mActivityManager.unbindBackupAgent(app);
// The agent was running with a stub Application object, so shut it down.
- if (app.uid != Process.SYSTEM_UID) {
+ if (app.uid != Process.SYSTEM_UID
+ && app.uid != Process.PHONE_UID) {
if (DEBUG) Slog.d(TAG, "Backup complete, killing host process");
mActivityManager.killApplicationProcess(app.processName, app.uid);
} else {
@@ -2121,6 +2445,7 @@
class PerformFullRestoreTask implements Runnable {
ParcelFileDescriptor mInputFile;
+ String mUserPassword;
IFullBackupRestoreObserver mObserver;
AtomicBoolean mLatchObject;
IBackupAgent mAgent;
@@ -2144,9 +2469,10 @@
// Packages we've already wiped data on when restoring their first file
final HashSet<String> mClearedPackages = new HashSet<String>();
- PerformFullRestoreTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
- AtomicBoolean latch) {
+ PerformFullRestoreTask(ParcelFileDescriptor fd, String password,
+ IFullBackupRestoreObserver observer, AtomicBoolean latch) {
mInputFile = fd;
+ mUserPassword = password;
mObserver = observer;
mLatchObject = latch;
mAgent = null;
@@ -2202,50 +2528,51 @@
mPackagePolicies.put("com.android.sharedstoragebackup", RestorePolicy.ACCEPT);
}
+ FileInputStream rawInStream = null;
+ DataInputStream rawDataIn = null;
try {
mBytes = 0;
byte[] buffer = new byte[32 * 1024];
- FileInputStream rawInStream = new FileInputStream(mInputFile.getFileDescriptor());
+ rawInStream = new FileInputStream(mInputFile.getFileDescriptor());
+ rawDataIn = new DataInputStream(rawInStream);
// First, parse out the unencrypted/uncompressed header
boolean compressed = false;
- boolean encrypted = false;
+ InputStream preCompressStream = rawInStream;
final InputStream in;
boolean okay = false;
final int headerLen = BACKUP_FILE_HEADER_MAGIC.length();
byte[] streamHeader = new byte[headerLen];
- try {
- int got;
- if ((got = rawInStream.read(streamHeader, 0, headerLen)) == headerLen) {
- byte[] magicBytes = BACKUP_FILE_HEADER_MAGIC.getBytes("UTF-8");
- if (Arrays.equals(magicBytes, streamHeader)) {
- // okay, header looks good. now parse out the rest of the fields.
- String s = readHeaderLine(rawInStream);
- if (Integer.parseInt(s) == BACKUP_FILE_VERSION) {
- // okay, it's a version we recognize
- s = readHeaderLine(rawInStream);
- compressed = (Integer.parseInt(s) != 0);
- s = readHeaderLine(rawInStream);
- if (!s.startsWith("-")) {
- encrypted = true;
- // TODO: parse out the salt here and process with the user pw
- }
+ rawDataIn.readFully(streamHeader);
+ byte[] magicBytes = BACKUP_FILE_HEADER_MAGIC.getBytes("UTF-8");
+ if (Arrays.equals(magicBytes, streamHeader)) {
+ // okay, header looks good. now parse out the rest of the fields.
+ String s = readHeaderLine(rawInStream);
+ if (Integer.parseInt(s) == BACKUP_FILE_VERSION) {
+ // okay, it's a version we recognize
+ s = readHeaderLine(rawInStream);
+ compressed = (Integer.parseInt(s) != 0);
+ s = readHeaderLine(rawInStream);
+ if (s.equals("none")) {
+ // no more header to parse; we're good to go
+ okay = true;
+ } else if (mUserPassword != null && mUserPassword.length() > 0) {
+ preCompressStream = decodeAesHeaderAndInitialize(s, rawInStream);
+ if (preCompressStream != null) {
okay = true;
- } else Slog.e(TAG, "Wrong header version: " + s);
- } else Slog.e(TAG, "Didn't read the right header magic");
- } else Slog.e(TAG, "Only read " + got + " bytes of header");
- } catch (NumberFormatException e) {
- Slog.e(TAG, "Can't parse restore data header");
- }
+ }
+ } else Slog.w(TAG, "Archive is encrypted but no password given");
+ } else Slog.w(TAG, "Wrong header version: " + s);
+ } else Slog.w(TAG, "Didn't read the right header magic");
if (!okay) {
- Slog.e(TAG, "Invalid restore data; aborting.");
+ Slog.w(TAG, "Invalid restore data; aborting.");
return;
}
// okay, use the right stream layer based on compression
- in = (compressed) ? new InflaterInputStream(rawInStream) : rawInStream;
+ in = (compressed) ? new InflaterInputStream(preCompressStream) : preCompressStream;
boolean didRestore;
do {
@@ -2260,6 +2587,8 @@
tearDownAgent(mTargetApp);
try {
+ if (rawDataIn != null) rawDataIn.close();
+ if (rawInStream != null) rawInStream.close();
mInputFile.close();
} catch (IOException e) {
Slog.w(TAG, "Close of restore data pipe threw", e);
@@ -2280,7 +2609,7 @@
String readHeaderLine(InputStream in) throws IOException {
int c;
- StringBuffer buffer = new StringBuffer(80);
+ StringBuilder buffer = new StringBuilder(80);
while ((c = in.read()) >= 0) {
if (c == '\n') break; // consume and discard the newlines
buffer.append((char)c);
@@ -2288,6 +2617,85 @@
return buffer.toString();
}
+ InputStream decodeAesHeaderAndInitialize(String encryptionName, InputStream rawInStream) {
+ InputStream result = null;
+ try {
+ if (encryptionName.equals(ENCRYPTION_ALGORITHM_NAME)) {
+
+ String userSaltHex = readHeaderLine(rawInStream); // 5
+ byte[] userSalt = hexToByteArray(userSaltHex);
+
+ String ckSaltHex = readHeaderLine(rawInStream); // 6
+ byte[] ckSalt = hexToByteArray(ckSaltHex);
+
+ int rounds = Integer.parseInt(readHeaderLine(rawInStream)); // 7
+ String userIvHex = readHeaderLine(rawInStream); // 8
+
+ String masterKeyBlobHex = readHeaderLine(rawInStream); // 9
+
+ // decrypt the master key blob
+ Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ SecretKey userKey = buildPasswordKey(mUserPassword, userSalt,
+ rounds);
+ byte[] IV = hexToByteArray(userIvHex);
+ IvParameterSpec ivSpec = new IvParameterSpec(IV);
+ c.init(Cipher.DECRYPT_MODE,
+ new SecretKeySpec(userKey.getEncoded(), "AES"),
+ ivSpec);
+ byte[] mkCipher = hexToByteArray(masterKeyBlobHex);
+ byte[] mkBlob = c.doFinal(mkCipher);
+
+ // first, the master key IV
+ int offset = 0;
+ int len = mkBlob[offset++];
+ IV = Arrays.copyOfRange(mkBlob, offset, offset + len);
+ offset += len;
+ // then the master key itself
+ len = mkBlob[offset++];
+ byte[] mk = Arrays.copyOfRange(mkBlob,
+ offset, offset + len);
+ offset += len;
+ // and finally the master key checksum hash
+ len = mkBlob[offset++];
+ byte[] mkChecksum = Arrays.copyOfRange(mkBlob,
+ offset, offset + len);
+
+ // now validate the decrypted master key against the checksum
+ byte[] calculatedCk = makeKeyChecksum(mk, ckSalt, rounds);
+ if (Arrays.equals(calculatedCk, mkChecksum)) {
+ ivSpec = new IvParameterSpec(IV);
+ c.init(Cipher.DECRYPT_MODE,
+ new SecretKeySpec(mk, "AES"),
+ ivSpec);
+ // Only if all of the above worked properly will 'result' be assigned
+ result = new CipherInputStream(rawInStream, c);
+ } else Slog.w(TAG, "Incorrect password");
+ } else Slog.w(TAG, "Unsupported encryption method: " + encryptionName);
+ } catch (InvalidAlgorithmParameterException e) {
+ Slog.e(TAG, "Needed parameter spec unavailable!", e);
+ } catch (BadPaddingException e) {
+ // This case frequently occurs when the wrong password is used to decrypt
+ // the master key. Use the identical "incorrect password" log text as is
+ // used in the checksum failure log in order to avoid providing additional
+ // information to an attacker.
+ Slog.w(TAG, "Incorrect password");
+ } catch (IllegalBlockSizeException e) {
+ Slog.w(TAG, "Invalid block size in master key");
+ } catch (NoSuchAlgorithmException e) {
+ Slog.e(TAG, "Needed decryption algorithm unavailable!");
+ } catch (NoSuchPaddingException e) {
+ Slog.e(TAG, "Needed padding mechanism unavailable!");
+ } catch (InvalidKeyException e) {
+ Slog.w(TAG, "Illegal password; aborting");
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Can't parse restore data header");
+ } catch (IOException e) {
+ Slog.w(TAG, "Can't read input header");
+ }
+
+ return result;
+ }
+
boolean restoreOneFile(InputStream instream, byte[] buffer) {
FileMetadata info;
try {
@@ -2540,7 +2948,7 @@
}
}
} catch (IOException e) {
- Slog.w(TAG, "io exception on restore socket read", e);
+ if (DEBUG) Slog.w(TAG, "io exception on restore socket read", e);
// treat as EOF
info = null;
}
@@ -2929,110 +3337,142 @@
boolean gotHeader = readTarHeader(instream, block);
if (gotHeader) {
- // okay, presume we're okay, and extract the various metadata
- info = new FileMetadata();
- info.size = extractRadix(block, 124, 12, 8);
- info.mtime = extractRadix(block, 136, 12, 8);
- info.mode = extractRadix(block, 100, 8, 8);
+ try {
+ // okay, presume we're okay, and extract the various metadata
+ info = new FileMetadata();
+ info.size = extractRadix(block, 124, 12, 8);
+ info.mtime = extractRadix(block, 136, 12, 8);
+ info.mode = extractRadix(block, 100, 8, 8);
- info.path = extractString(block, 345, 155); // prefix
- String path = extractString(block, 0, 100);
- if (path.length() > 0) {
- if (info.path.length() > 0) info.path += '/';
- info.path += path;
- }
-
- // tar link indicator field: 1 byte at offset 156 in the header.
- int typeChar = block[156];
- if (typeChar == 'x') {
- // pax extended header, so we need to read that
- gotHeader = readPaxExtendedHeader(instream, info);
- if (gotHeader) {
- // and after a pax extended header comes another real header -- read
- // that to find the real file type
- gotHeader = readTarHeader(instream, block);
+ info.path = extractString(block, 345, 155); // prefix
+ String path = extractString(block, 0, 100);
+ if (path.length() > 0) {
+ if (info.path.length() > 0) info.path += '/';
+ info.path += path;
}
- if (!gotHeader) throw new IOException("Bad or missing pax header");
- typeChar = block[156];
- }
-
- switch (typeChar) {
- case '0': info.type = BackupAgent.TYPE_FILE; break;
- case '5': {
- info.type = BackupAgent.TYPE_DIRECTORY;
- if (info.size != 0) {
- Slog.w(TAG, "Directory entry with nonzero size in header");
- info.size = 0;
+ // tar link indicator field: 1 byte at offset 156 in the header.
+ int typeChar = block[156];
+ if (typeChar == 'x') {
+ // pax extended header, so we need to read that
+ gotHeader = readPaxExtendedHeader(instream, info);
+ if (gotHeader) {
+ // and after a pax extended header comes another real header -- read
+ // that to find the real file type
+ gotHeader = readTarHeader(instream, block);
}
- break;
+ if (!gotHeader) throw new IOException("Bad or missing pax header");
+
+ typeChar = block[156];
}
- case 0: {
- // presume EOF
- if (DEBUG) Slog.w(TAG, "Saw type=0 in tar header block, info=" + info);
- return null;
- }
- default: {
- Slog.e(TAG, "Unknown tar entity type: " + typeChar);
- throw new IOException("Unknown entity type " + typeChar);
- }
- }
- // Parse out the path
- //
- // first: apps/shared/unrecognized
- if (FullBackup.SHARED_PREFIX.regionMatches(0,
- info.path, 0, FullBackup.SHARED_PREFIX.length())) {
- // File in shared storage. !!! TODO: implement this.
- info.path = info.path.substring(FullBackup.SHARED_PREFIX.length());
- info.packageName = "com.android.sharedstoragebackup";
- info.domain = FullBackup.SHARED_STORAGE_TOKEN;
- if (DEBUG) Slog.i(TAG, "File in shared storage: " + info.path);
- } else if (FullBackup.APPS_PREFIX.regionMatches(0,
- info.path, 0, FullBackup.APPS_PREFIX.length())) {
- // App content! Parse out the package name and domain
-
- // strip the apps/ prefix
- info.path = info.path.substring(FullBackup.APPS_PREFIX.length());
-
- // extract the package name
- int slash = info.path.indexOf('/');
- if (slash < 0) throw new IOException("Illegal semantic path in " + info.path);
- info.packageName = info.path.substring(0, slash);
- info.path = info.path.substring(slash+1);
-
- // if it's a manifest we're done, otherwise parse out the domains
- if (!info.path.equals(BACKUP_MANIFEST_FILENAME)) {
- slash = info.path.indexOf('/');
- if (slash < 0) throw new IOException("Illegal semantic path in non-manifest " + info.path);
- info.domain = info.path.substring(0, slash);
- // validate that it's one of the domains we understand
- if (!info.domain.equals(FullBackup.APK_TREE_TOKEN)
- && !info.domain.equals(FullBackup.DATA_TREE_TOKEN)
- && !info.domain.equals(FullBackup.DATABASE_TREE_TOKEN)
- && !info.domain.equals(FullBackup.ROOT_TREE_TOKEN)
- && !info.domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)
- && !info.domain.equals(FullBackup.OBB_TREE_TOKEN)
- && !info.domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
- throw new IOException("Unrecognized domain " + info.domain);
+ switch (typeChar) {
+ case '0': info.type = BackupAgent.TYPE_FILE; break;
+ case '5': {
+ info.type = BackupAgent.TYPE_DIRECTORY;
+ if (info.size != 0) {
+ Slog.w(TAG, "Directory entry with nonzero size in header");
+ info.size = 0;
+ }
+ break;
}
-
- info.path = info.path.substring(slash + 1);
+ case 0: {
+ // presume EOF
+ if (DEBUG) Slog.w(TAG, "Saw type=0 in tar header block, info=" + info);
+ return null;
+ }
+ default: {
+ Slog.e(TAG, "Unknown tar entity type: " + typeChar);
+ throw new IOException("Unknown entity type " + typeChar);
+ }
}
+
+ // Parse out the path
+ //
+ // first: apps/shared/unrecognized
+ if (FullBackup.SHARED_PREFIX.regionMatches(0,
+ info.path, 0, FullBackup.SHARED_PREFIX.length())) {
+ // File in shared storage. !!! TODO: implement this.
+ info.path = info.path.substring(FullBackup.SHARED_PREFIX.length());
+ info.packageName = "com.android.sharedstoragebackup";
+ info.domain = FullBackup.SHARED_STORAGE_TOKEN;
+ if (DEBUG) Slog.i(TAG, "File in shared storage: " + info.path);
+ } else if (FullBackup.APPS_PREFIX.regionMatches(0,
+ info.path, 0, FullBackup.APPS_PREFIX.length())) {
+ // App content! Parse out the package name and domain
+
+ // strip the apps/ prefix
+ info.path = info.path.substring(FullBackup.APPS_PREFIX.length());
+
+ // extract the package name
+ int slash = info.path.indexOf('/');
+ if (slash < 0) throw new IOException("Illegal semantic path in " + info.path);
+ info.packageName = info.path.substring(0, slash);
+ info.path = info.path.substring(slash+1);
+
+ // if it's a manifest we're done, otherwise parse out the domains
+ if (!info.path.equals(BACKUP_MANIFEST_FILENAME)) {
+ slash = info.path.indexOf('/');
+ if (slash < 0) throw new IOException("Illegal semantic path in non-manifest " + info.path);
+ info.domain = info.path.substring(0, slash);
+ // validate that it's one of the domains we understand
+ if (!info.domain.equals(FullBackup.APK_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.DATA_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.DATABASE_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.ROOT_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.OBB_TREE_TOKEN)
+ && !info.domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
+ throw new IOException("Unrecognized domain " + info.domain);
+ }
+
+ info.path = info.path.substring(slash + 1);
+ }
+ }
+ } catch (IOException e) {
+ if (DEBUG) {
+ Slog.e(TAG, "Parse error in header. Hexdump:");
+ HEXLOG(block);
+ }
+ throw e;
}
}
return info;
}
- boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
- int nRead = instream.read(block, 0, 512);
- if (nRead >= 0) mBytes += nRead;
- if (nRead > 0 && nRead != 512) {
- // if we read only a partial block, then things are
- // clearly screwed up. terminate the restore.
- throw new IOException("Partial header block: " + nRead);
+ private void HEXLOG(byte[] block) {
+ int offset = 0;
+ int todo = block.length;
+ StringBuilder buf = new StringBuilder(64);
+ while (todo > 0) {
+ buf.append(String.format("%04x ", offset));
+ int numThisLine = (todo > 16) ? 16 : todo;
+ for (int i = 0; i < numThisLine; i++) {
+ buf.append(String.format("%02x ", block[offset+i]));
+ }
+ Slog.i("hexdump", buf.toString());
+ buf.setLength(0);
+ todo -= numThisLine;
+ offset += numThisLine;
}
- return (nRead > 0);
+ }
+
+ boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
+ int totalRead = 0;
+ while (totalRead < 512) {
+ int nRead = instream.read(block, totalRead, 512 - totalRead);
+ if (nRead >= 0) {
+ mBytes += nRead;
+ totalRead += nRead;
+ } else {
+ if (totalRead == 0) {
+ // EOF instead of a new header; we're done
+ break;
+ }
+ throw new IOException("Unable to read full block header, t=" + totalRead);
+ }
+ }
+ return (totalRead == 512);
}
// overwrites 'info' fields based on the pax extended header
@@ -3102,7 +3542,7 @@
// Numeric fields in tar can terminate with either NUL or SPC
if (b == 0 || b == ' ') break;
if (b < '0' || b > ('0' + radix - 1)) {
- throw new IOException("Invalid number in header");
+ throw new IOException("Invalid number in header: '" + (char)b + "' for radix " + radix);
}
value = radix * value + (b - '0');
}
@@ -3930,7 +4370,7 @@
}
public void fullRestore(ParcelFileDescriptor fd) {
- mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup");
+ mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullRestore");
Slog.i(TAG, "Beginning full restore...");
long oldId = Binder.clearCallingIdentity();
@@ -4011,14 +4451,15 @@
// Confirm that the previously-requested full backup/restore operation can proceed. This
// is used to require a user-facing disclosure about the operation.
+ @Override
public void acknowledgeFullBackupOrRestore(int token, boolean allow,
- IFullBackupRestoreObserver observer) {
+ String password, IFullBackupRestoreObserver observer) {
if (DEBUG) Slog.d(TAG, "acknowledgeFullBackupOrRestore : token=" + token
+ " allow=" + allow);
// TODO: possibly require not just this signature-only permission, but even
// require that the specific designated confirmation-UI app uid is the caller?
- mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup");
+ mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "acknowledgeFullBackupOrRestore");
long oldId = Binder.clearCallingIdentity();
try {
@@ -4032,6 +4473,7 @@
if (allow) {
params.observer = observer;
+ params.password = password;
final int verb = params instanceof FullBackupParams
? MSG_RUN_FULL_BACKUP
: MSG_RUN_FULL_RESTORE;
@@ -4057,7 +4499,7 @@
// Enable/disable the backup service
public void setBackupEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "setBackupEnabled");
+ "setBackupEnabled");
Slog.i(TAG, "Backup enabled => " + enable);
@@ -4102,7 +4544,7 @@
// Enable/disable automatic restore of app data at install time
public void setAutoRestore(boolean doAutoRestore) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "setBackupEnabled");
+ "setAutoRestore");
Slog.i(TAG, "Auto restore => " + doAutoRestore);
@@ -4236,7 +4678,7 @@
// This string is used VERBATIM as the summary text of the relevant Settings item!
public String getDestinationString(String transportName) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "getConfigurationIntent");
+ "getDestinationString");
synchronized (mTransports) {
final IBackupTransport transport = mTransports.get(transportName);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 79c0675..9a9cc8f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1926,7 +1926,8 @@
}
// Caller must grab mDnsLock.
- private boolean updateDns(String network, Collection<InetAddress> dnses, String domains) {
+ private boolean updateDns(String network, String iface,
+ Collection<InetAddress> dnses, String domains) {
boolean changed = false;
int last = 0;
if (dnses.size() == 0 && mDefaultDns != null) {
@@ -1962,6 +1963,14 @@
}
mNumDnsEntries = last;
+ if (changed) {
+ try {
+ mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
+ mNetd.setDefaultInterfaceForDns(iface);
+ } catch (Exception e) {
+ Slog.e(TAG, "exception setting default dns interface: " + e);
+ }
+ }
if (!domains.equals(SystemProperties.get("net.dns.search"))) {
SystemProperties.set("net.dns.search", domains);
changed = true;
@@ -1981,10 +1990,16 @@
String network = nt.getNetworkInfo().getTypeName();
synchronized (mDnsLock) {
if (!mDnsOverridden) {
- changed = updateDns(network, dnses, "");
+ changed = updateDns(network, p.getInterfaceName(), dnses, "");
}
}
} else {
+ try {
+ mNetd.setDnsServersForInterface(p.getInterfaceName(),
+ NetworkUtils.makeStrings(dnses));
+ } catch (Exception e) {
+ Slog.e(TAG, "exception setting dns servers: " + e);
+ }
// set per-pid dns for attached secondary nets
List pids = mNetRequestersPids[netType];
for (int y=0; y< pids.size(); y++) {
@@ -2686,7 +2701,7 @@
// Apply DNS changes.
boolean changed = false;
synchronized (mDnsLock) {
- changed = updateDns("VPN", addresses, domains);
+ changed = updateDns("VPN", "VPN", addresses, domains);
mDnsOverridden = true;
}
if (changed) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 17ad268..39d2b1c 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -125,10 +125,14 @@
private Thread mThread;
private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
+ // TODO: replace with RemoteCallbackList
private ArrayList<INetworkManagementEventObserver> mObservers;
+ private Object mQuotaLock = new Object();
/** Set of interfaces with active quotas. */
- private HashSet<String> mInterfaceQuota = Sets.newHashSet();
+ private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
+ /** Set of interfaces with active alerts. */
+ private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
/** Set of UIDs with active reject rules. */
private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
@@ -1058,26 +1062,25 @@
}
@Override
- public void setInterfaceQuota(String iface, long quota) {
+ public void setInterfaceQuota(String iface, long quotaBytes) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
// silently discard when control disabled
// TODO: eventually migrate to be always enabled
if (!mBandwidthControlEnabled) return;
- synchronized (mInterfaceQuota) {
- if (mInterfaceQuota.contains(iface)) {
- // TODO: eventually consider throwing
- return;
+ synchronized (mQuotaLock) {
+ if (mActiveQuotaIfaces.contains(iface)) {
+ throw new IllegalStateException("iface " + iface + " already has quota");
}
final StringBuilder command = new StringBuilder();
- command.append("bandwidth setiquota ").append(iface).append(" ").append(quota);
+ command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes);
try {
- // TODO: add support for quota shared across interfaces
+ // TODO: support quota shared across interfaces
mConnector.doCommand(command.toString());
- mInterfaceQuota.add(iface);
+ mActiveQuotaIfaces.add(iface);
} catch (NativeDaemonConnectorException e) {
throw new IllegalStateException("Error communicating to native daemon", e);
}
@@ -1092,8 +1095,8 @@
// TODO: eventually migrate to be always enabled
if (!mBandwidthControlEnabled) return;
- synchronized (mInterfaceQuota) {
- if (!mInterfaceQuota.contains(iface)) {
+ synchronized (mQuotaLock) {
+ if (!mActiveQuotaIfaces.contains(iface)) {
// TODO: eventually consider throwing
return;
}
@@ -1102,9 +1105,10 @@
command.append("bandwidth removeiquota ").append(iface);
try {
- // TODO: add support for quota shared across interfaces
+ // TODO: support quota shared across interfaces
mConnector.doCommand(command.toString());
- mInterfaceQuota.remove(iface);
+ mActiveQuotaIfaces.remove(iface);
+ mActiveAlertIfaces.remove(iface);
} catch (NativeDaemonConnectorException e) {
throw new IllegalStateException("Error communicating to native daemon", e);
}
@@ -1112,6 +1116,83 @@
}
@Override
+ public void setInterfaceAlert(String iface, long alertBytes) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ // silently discard when control disabled
+ // TODO: eventually migrate to be always enabled
+ if (!mBandwidthControlEnabled) return;
+
+ // quick sanity check
+ if (!mActiveQuotaIfaces.contains(iface)) {
+ throw new IllegalStateException("setting alert requires existing quota on iface");
+ }
+
+ synchronized (mQuotaLock) {
+ if (mActiveAlertIfaces.contains(iface)) {
+ throw new IllegalStateException("iface " + iface + " already has alert");
+ }
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth setinterfacealert ").append(iface).append(" ").append(
+ alertBytes);
+
+ try {
+ // TODO: support alert shared across interfaces
+ mConnector.doCommand(command.toString());
+ mActiveAlertIfaces.add(iface);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+ }
+ }
+
+ @Override
+ public void removeInterfaceAlert(String iface) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ // silently discard when control disabled
+ // TODO: eventually migrate to be always enabled
+ if (!mBandwidthControlEnabled) return;
+
+ synchronized (mQuotaLock) {
+ if (!mActiveAlertIfaces.contains(iface)) {
+ // TODO: eventually consider throwing
+ return;
+ }
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth removeinterfacealert ").append(iface);
+
+ try {
+ // TODO: support alert shared across interfaces
+ mConnector.doCommand(command.toString());
+ mActiveAlertIfaces.remove(iface);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+ }
+ }
+
+ @Override
+ public void setGlobalAlert(long alertBytes) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ // silently discard when control disabled
+ // TODO: eventually migrate to be always enabled
+ if (!mBandwidthControlEnabled) return;
+
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth setglobalalert ").append(alertBytes);
+
+ try {
+ mConnector.doCommand(command.toString());
+ } 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);
@@ -1375,18 +1456,17 @@
try {
String cmd = "resolver setifdns " + iface;
for (String s : servers) {
- if (s != null && !"0.0.0.0".equals(s) &&
- !"::".equals(s) && !"0:0:0:0:0:0:0:0".equals(s)) {
- cmd += " " + InetAddress.getByName(s).getHostAddress();
+ InetAddress a = NetworkUtils.numericToInetAddress(s);
+ if (a.isAnyLocalAddress() == false) {
+ cmd += " " + a.getHostAddress();
}
}
-
mConnector.doCommand(cmd);
- } catch (UnknownHostException e) {
- throw new IllegalStateException("failed to resolve dns address.", e);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalStateException("Error setting dnsn for interface", e);
} catch (NativeDaemonConnectorException e) {
throw new IllegalStateException(
- "Error communicating with native deamon to set dns for interface", e);
+ "Error communicating with native daemon to set dns for interface", e);
}
}
@@ -1412,7 +1492,7 @@
mConnector.doCommand(cmd);
} catch (NativeDaemonConnectorException e) {
throw new IllegalStateException(
- "Error communicating with native deamon to flush interface " + iface, e);
+ "Error communicating with native daemon to flush interface " + iface, e);
}
}
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 5d7a48f..8031c4e 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -469,6 +469,24 @@
record = mToastQueue.get(index);
record.update(duration);
} else {
+ // Limit the number of toasts that any given package except the android
+ // package can enqueue. Prevents DOS attacks and deals with leaks.
+ if (!"android".equals(pkg)) {
+ int count = 0;
+ final int N = mToastQueue.size();
+ for (int i=0; i<N; i++) {
+ final ToastRecord r = mToastQueue.get(i);
+ if (r.pkg.equals(pkg)) {
+ count++;
+ if (count >= MAX_PACKAGE_NOTIFICATIONS) {
+ Slog.e(TAG, "Package has already posted " + count
+ + " toasts. Not showing more. Package=" + pkg);
+ return;
+ }
+ }
+ }
+ }
+
record = new ToastRecord(callingPid, pkg, callback, duration);
mToastQueue.add(record);
index = mToastQueue.size() - 1;
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index 950f3b6..da97089 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -21,6 +21,7 @@
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
import android.app.backup.WallpaperBackupHelper;
import android.content.Context;
import android.os.ParcelFileDescriptor;
@@ -53,13 +54,6 @@
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
- if (oldState == null) {
- // Ah, it's a full backup dataset, being restored piecemeal. Just
- // pop over to the full restore handling and we're done.
- runFullBackup(data);
- return;
- }
-
// We only back up the data under the current "wallpaper" schema with metadata
WallpaperManagerService wallpaper = (WallpaperManagerService)ServiceManager.getService(
Context.WALLPAPER_SERVICE);
@@ -74,19 +68,21 @@
super.onBackup(oldState, data, newState);
}
- private void runFullBackup(BackupDataOutput output) {
- fullWallpaperBackup(output);
+ @Override
+ public void onFullBackup(FullBackupDataOutput data) throws IOException {
+ // At present we back up only the wallpaper
+ fullWallpaperBackup(data);
}
- private void fullWallpaperBackup(BackupDataOutput output) {
+ private void fullWallpaperBackup(FullBackupDataOutput output) {
// Back up the data files directly. We do them in this specific order --
// info file followed by image -- because then we need take no special
// steps during restore; the restore will happen properly when the individual
// files are restored piecemeal.
FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
- WALLPAPER_INFO_DIR, WALLPAPER_INFO, output);
+ WALLPAPER_INFO_DIR, WALLPAPER_INFO, output.getData());
FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null,
- WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output);
+ WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output.getData());
}
@Override
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index ffdc288..837778e 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -30,6 +30,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -72,6 +73,16 @@
synchronized (mSpellCheckerMap) {
buildSpellCheckerMapLocked(context, mSpellCheckerList, mSpellCheckerMap);
}
+ SpellCheckerInfo sci = getCurrentSpellChecker(null);
+ if (sci == null) {
+ sci = findAvailSpellCheckerLocked(null, null);
+ if (sci != null) {
+ // Set the current spell checker if there is one or more spell checkers
+ // available. In this case, "sci" is the first one in the available spell
+ // checkers.
+ setCurrentSpellCheckerLocked(sci);
+ }
+ }
}
private class TextServicesMonitor extends PackageMonitor {
@@ -81,22 +92,15 @@
buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap);
// TODO: Update for each locale
SpellCheckerInfo sci = getCurrentSpellChecker(null);
- if (sci == null) {
- sci = findAvailSpellCheckerLocked(null, null);
- if (sci == null) return;
- // Set the current spell checker if there is one or more spell checkers
- // available. In this case, "sci" is the first one in the available spell
- // checkers.
- setCurrentSpellChecker(sci);
- }
+ if (sci == null) return;
final String packageName = sci.getPackageName();
final int change = isPackageDisappearing(packageName);
if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
// Package disappearing
- setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+ setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
} else if (isPackageModified(packageName)) {
// Package modified
- setCurrentSpellChecker(findAvailSpellCheckerLocked(null, packageName));
+ setCurrentSpellCheckerLocked(findAvailSpellCheckerLocked(null, packageName));
}
}
}
@@ -125,6 +129,9 @@
list.add(sci);
map.put(sci.getId(), sci);
}
+ if (DBG) {
+ Slog.d(TAG, "buildSpellCheckerMapLocked: " + list.size() + "," + map.size());
+ }
}
// TODO: find an appropriate spell checker for specified locale
@@ -138,6 +145,9 @@
for (int i = 0; i < spellCheckersCount; ++i) {
final SpellCheckerInfo sci = mSpellCheckerList.get(i);
if (prefPackage.equals(sci.getPackageName())) {
+ if (DBG) {
+ Slog.d(TAG, "findAvailSpellCheckerLocked: " + sci.getPackageName());
+ }
return sci;
}
}
@@ -153,7 +163,7 @@
@Override
public SpellCheckerInfo getCurrentSpellChecker(String locale) {
synchronized (mSpellCheckerMap) {
- final String curSpellCheckerId =
+ String curSpellCheckerId =
Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.SPELL_CHECKER_SERVICE);
if (DBG) {
@@ -172,7 +182,7 @@
if (!mSystemReady) {
return;
}
- if (info == null || tsListener == null) {
+ if (info == null || tsListener == null || scListener == null) {
Slog.e(TAG, "getSpellCheckerService: Invalid input.");
return;
}
@@ -181,32 +191,96 @@
if (!mSpellCheckerMap.containsKey(sciId)) {
return;
}
+ final int uid = Binder.getCallingUid();
if (mSpellCheckerBindGroups.containsKey(sciId)) {
- mSpellCheckerBindGroups.get(sciId).addListener(tsListener, locale, scListener);
- return;
+ final SpellCheckerBindGroup bindGroup = mSpellCheckerBindGroups.get(sciId);
+ if (bindGroup != null) {
+ final InternalDeathRecipient recipient =
+ mSpellCheckerBindGroups.get(sciId).addListener(
+ tsListener, locale, scListener, uid);
+ if (recipient == null) {
+ if (DBG) {
+ Slog.w(TAG, "Didn't create a death recipient.");
+ }
+ return;
+ }
+ if (bindGroup.mSpellChecker == null & bindGroup.mConnected) {
+ Slog.e(TAG, "The state of the spell checker bind group is illegal.");
+ bindGroup.removeAll();
+ } else if (bindGroup.mSpellChecker != null) {
+ if (DBG) {
+ Slog.w(TAG, "Existing bind found. Return a spell checker session now. "
+ + "Listeners count = " + bindGroup.mListeners.size());
+ }
+ try {
+ final ISpellCheckerSession session =
+ bindGroup.mSpellChecker.getISpellCheckerSession(
+ recipient.mScLocale, recipient.mScListener);
+ if (session != null) {
+ tsListener.onServiceConnected(session);
+ return;
+ } else {
+ if (DBG) {
+ Slog.w(TAG, "Existing bind already expired. ");
+ }
+ bindGroup.removeAll();
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception in getting spell checker session: " + e);
+ bindGroup.removeAll();
+ }
+ }
+ }
}
- final InternalServiceConnection connection = new InternalServiceConnection(
- sciId, locale, scListener);
- final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
- serviceIntent.setComponent(info.getComponent());
- if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
- Slog.e(TAG, "Failed to get a spell checker service.");
- return;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ startSpellCheckerServiceInnerLocked(info, locale, tsListener, scListener, uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
- connection, tsListener, locale, scListener);
- mSpellCheckerBindGroups.put(sciId, group);
}
return;
}
+ private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale,
+ ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener,
+ int uid) {
+ if (DBG) {
+ Slog.w(TAG, "Start spell checker session inner locked.");
+ }
+ final String sciId = info.getId();
+ final InternalServiceConnection connection = new InternalServiceConnection(
+ sciId, locale, scListener);
+ final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
+ serviceIntent.setComponent(info.getComponent());
+ if (DBG) {
+ Slog.w(TAG, "bind service: " + info.getId());
+ }
+ if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
+ Slog.e(TAG, "Failed to get a spell checker service.");
+ return;
+ }
+ final SpellCheckerBindGroup group = new SpellCheckerBindGroup(
+ connection, tsListener, locale, scListener, uid);
+ mSpellCheckerBindGroups.put(sciId, group);
+ }
+
@Override
public SpellCheckerInfo[] getEnabledSpellCheckers() {
+ if (DBG) {
+ Slog.d(TAG, "getEnabledSpellCheckers: " + mSpellCheckerList.size());
+ for (int i = 0; i < mSpellCheckerList.size(); ++i) {
+ Slog.d(TAG, "EnabledSpellCheckers: " + mSpellCheckerList.get(i).getPackageName());
+ }
+ }
return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]);
}
@Override
public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
+ if (DBG) {
+ Slog.d(TAG, "FinishSpellCheckerService");
+ }
synchronized(mSpellCheckerMap) {
for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
if (group == null) continue;
@@ -215,31 +289,57 @@
}
}
- private void setCurrentSpellChecker(SpellCheckerInfo sci) {
+ @Override
+ public void setCurrentSpellChecker(SpellCheckerInfo sci) {
+ synchronized(mSpellCheckerMap) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Requires permission "
+ + android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ }
+ setCurrentSpellCheckerLocked(sci);
+ }
+ }
+
+ private void setCurrentSpellCheckerLocked(SpellCheckerInfo sci) {
if (DBG) {
Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
}
- if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+ if (sci == null || !mSpellCheckerMap.containsKey(sci.getId())) return;
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
// SpellCheckerBindGroup contains active text service session listeners.
// If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
// mSpellCheckerBindGroups
private class SpellCheckerBindGroup {
- final InternalServiceConnection mInternalConnection;
- final ArrayList<InternalDeathRecipient> mListeners =
+ private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
+ private final InternalServiceConnection mInternalConnection;
+ private final ArrayList<InternalDeathRecipient> mListeners =
new ArrayList<InternalDeathRecipient>();
+ public ISpellCheckerService mSpellChecker;
+ public boolean mConnected;
public SpellCheckerBindGroup(InternalServiceConnection connection,
ITextServicesSessionListener listener, String locale,
- ISpellCheckerSessionListener scListener) {
+ ISpellCheckerSessionListener scListener, int uid) {
mInternalConnection = connection;
- addListener(listener, locale, scListener);
+ mConnected = false;
+ addListener(listener, locale, scListener, uid);
}
public void onServiceConnected(ISpellCheckerService spellChecker) {
+ if (DBG) {
+ Slog.d(TAG, "onServiceConnected");
+ }
synchronized(mSpellCheckerMap) {
for (InternalDeathRecipient listener : mListeners) {
try {
@@ -247,35 +347,47 @@
listener.mScLocale, listener.mScListener);
listener.mTsListener.onServiceConnected(session);
} catch (RemoteException e) {
+ Slog.e(TAG, "Exception in getting the spell checker session: " + e);
+ removeAll();
+ return;
}
}
+ mSpellChecker = spellChecker;
+ mConnected = true;
}
}
- public void addListener(ITextServicesSessionListener tsListener, String locale,
- ISpellCheckerSessionListener scListener) {
+ public InternalDeathRecipient addListener(ITextServicesSessionListener tsListener,
+ String locale, ISpellCheckerSessionListener scListener, int uid) {
+ if (DBG) {
+ Slog.d(TAG, "addListener: " + locale);
+ }
+ InternalDeathRecipient recipient = null;
synchronized(mSpellCheckerMap) {
try {
final int size = mListeners.size();
for (int i = 0; i < size; ++i) {
if (mListeners.get(i).hasSpellCheckerListener(scListener)) {
// do not add the lister if the group already contains this.
- return;
+ return null;
}
}
- final InternalDeathRecipient recipient = new InternalDeathRecipient(
- this, tsListener, locale, scListener);
+ recipient = new InternalDeathRecipient(
+ this, tsListener, locale, scListener, uid);
scListener.asBinder().linkToDeath(recipient, 0);
- mListeners.add(new InternalDeathRecipient(
- this, tsListener, locale, scListener));
+ mListeners.add(recipient);
} catch(RemoteException e) {
// do nothing
}
cleanLocked();
}
+ return recipient;
}
public void removeListener(ISpellCheckerSessionListener listener) {
+ if (DBG) {
+ Slog.w(TAG, "remove listener: " + listener.hashCode());
+ }
synchronized(mSpellCheckerMap) {
final int size = mListeners.size();
final ArrayList<InternalDeathRecipient> removeList =
@@ -283,11 +395,17 @@
for (int i = 0; i < size; ++i) {
final InternalDeathRecipient tempRecipient = mListeners.get(i);
if(tempRecipient.hasSpellCheckerListener(listener)) {
+ if (DBG) {
+ Slog.w(TAG, "found existing listener.");
+ }
removeList.add(tempRecipient);
}
}
final int removeSize = removeList.size();
for (int i = 0; i < removeSize; ++i) {
+ if (DBG) {
+ Slog.w(TAG, "Remove " + removeList.get(i));
+ }
mListeners.remove(removeList.get(i));
}
cleanLocked();
@@ -295,12 +413,25 @@
}
private void cleanLocked() {
+ if (DBG) {
+ Slog.d(TAG, "cleanLocked");
+ }
if (mListeners.isEmpty()) {
- mSpellCheckerBindGroups.remove(this);
+ if (mSpellCheckerBindGroups.containsKey(this)) {
+ mSpellCheckerBindGroups.remove(this);
+ }
// Unbind service when there is no active clients.
mContext.unbindService(mInternalConnection);
}
}
+
+ public void removeAll() {
+ Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
+ synchronized(mSpellCheckerMap) {
+ mListeners.clear();
+ cleanLocked();
+ }
+ }
}
private class InternalServiceConnection implements ServiceConnection {
@@ -317,6 +448,9 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized(mSpellCheckerMap) {
+ if (DBG) {
+ Slog.w(TAG, "onServiceConnected: " + name);
+ }
ISpellCheckerService spellChecker = ISpellCheckerService.Stub.asInterface(service);
final SpellCheckerBindGroup group = mSpellCheckerBindGroups.get(mSciId);
if (group != null) {
@@ -336,17 +470,19 @@
public final ISpellCheckerSessionListener mScListener;
public final String mScLocale;
private final SpellCheckerBindGroup mGroup;
+ public final int mUid;
public InternalDeathRecipient(SpellCheckerBindGroup group,
ITextServicesSessionListener tsListener, String scLocale,
- ISpellCheckerSessionListener scListener) {
+ ISpellCheckerSessionListener scListener, int uid) {
mTsListener = tsListener;
mScListener = scListener;
mScLocale = scLocale;
mGroup = group;
+ mUid = uid;
}
public boolean hasSpellCheckerListener(ISpellCheckerSessionListener listener) {
- return mScListener.equals(listener);
+ return listener.asBinder().equals(mScListener.asBinder());
}
@Override
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index c39dc80..de25747 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -383,6 +383,12 @@
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
synchronized (mVibrations) {
doCancelVibrateLocked();
+
+ int size = mVibrations.size();
+ for(int i = 0; i < size; i++) {
+ unlinkVibration(mVibrations.get(i));
+ }
+
mVibrations.clear();
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index bb9d15b..d0f8843 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -49,6 +49,7 @@
import android.view.IWindow;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -129,10 +130,10 @@
private boolean mIsAccessibilityEnabled;
- private boolean mIsTouchExplorationRequested;
-
private AccessibilityInputFilter mInputFilter;
+ private boolean mHasInputFilter;
+
private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
private boolean mIsTouchExplorationEnabled;
@@ -189,7 +190,7 @@
manageServicesLocked();
}
}
-
+
@Override
public boolean onHandleForceStop(Intent intent, String[] packages,
int uid, boolean doit) {
@@ -236,17 +237,16 @@
mIsAccessibilityEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
- // if accessibility is enabled inform our clients we are on
- if (mIsAccessibilityEnabled) {
- sendAccessibilityEnabledToClientsLocked();
- }
+
manageServicesLocked();
// get touch exploration enabled setting on boot
- mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mIsTouchExplorationEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
- updateTouchExplorationEnabledLocked();
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+ updateInputFilterLocked();
+
+ sendStateToClientsLocked();
}
return;
@@ -288,13 +288,13 @@
} else {
unbindAllServicesLocked();
}
- sendAccessibilityEnabledToClientsLocked();
+ sendStateToClientsLocked();
}
}
});
Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED);
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED);
contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
new ContentObserver(new Handler()) {
@Override
@@ -302,10 +302,11 @@
super.onChange(selfChange);
synchronized (mLock) {
- mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mIsTouchExplorationEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
- updateTouchExplorationEnabledLocked();
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+ updateInputFilterLocked();
+ sendStateToClientsLocked();
}
}
});
@@ -325,7 +326,7 @@
});
}
- public boolean addClient(IAccessibilityManagerClient client) throws RemoteException {
+ public int addClient(IAccessibilityManagerClient client) throws RemoteException {
synchronized (mLock) {
final IAccessibilityManagerClient addedClient = client;
mClients.add(addedClient);
@@ -338,7 +339,7 @@
}
}
}, 0);
- return mIsAccessibilityEnabled;
+ return getState();
}
}
@@ -628,7 +629,7 @@
service.linkToOwnDeath();
mServices.add(service);
mComponentNameToServiceMap.put(service.mComponentName, service);
- updateTouchExplorationEnabledLocked();
+ updateInputFilterLocked();
} catch (RemoteException e) {
/* do nothing */
}
@@ -648,7 +649,7 @@
mComponentNameToServiceMap.remove(service.mComponentName);
mHandler.removeMessages(service.mId);
service.unlinkToOwnDeath();
- updateTouchExplorationEnabledLocked();
+ updateInputFilterLocked();
return removed;
}
@@ -781,12 +782,13 @@
}
/**
- * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients.
+ * Sends the state to the clients.
*/
- private void sendAccessibilityEnabledToClientsLocked() {
+ private void sendStateToClientsLocked() {
+ final int state = getState();
for (int i = 0, count = mClients.size(); i < count; i++) {
try {
- mClients.get(i).setEnabled(mIsAccessibilityEnabled);
+ mClients.get(i).setState(state);
} catch (RemoteException re) {
mClients.remove(i);
count--;
@@ -796,48 +798,39 @@
}
/**
- * Sends the touch exploration state to clients.
+ * Gets the current state as a set of flags.
+ *
+ * @return The state.
*/
- private void sendTouchExplorationEnabledToClientsLocked() {
- for (int i = 0, count = mClients.size(); i < count; i++) {
- try {
- mClients.get(i).setTouchExplorationEnabled(mIsTouchExplorationEnabled);
- } catch (RemoteException re) {
- mClients.remove(i);
- count--;
- i--;
- }
+ private int getState() {
+ int state = 0;
+ if (mIsAccessibilityEnabled) {
+ state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
+ // Touch exploration relies on enabled accessibility.
+ if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+ }
+ return state;
}
/**
- * Updates the touch exploration state. Touch exploration is enabled if it
- * is requested, accessibility is on and there is at least one enabled
- * accessibility service providing spoken feedback.
+ * Updates the touch exploration state.
*/
- private void updateTouchExplorationEnabledLocked() {
- if (mIsAccessibilityEnabled && mIsTouchExplorationRequested) {
- final boolean hasSpeakingServicesEnabled = !getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
- if (!mIsTouchExplorationEnabled) {
- if (!hasSpeakingServicesEnabled) {
- return;
- }
+ private void updateInputFilterLocked() {
+ if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ if (!mHasInputFilter) {
+ mHasInputFilter = true;
if (mInputFilter == null) {
mInputFilter = new AccessibilityInputFilter(mContext);
}
mWindowManagerService.setInputFilter(mInputFilter);
- mIsTouchExplorationEnabled = true;
- sendTouchExplorationEnabledToClientsLocked();
- return;
- } else if (hasSpeakingServicesEnabled) {
- return;
}
+ return;
}
- if (mIsTouchExplorationEnabled) {
+ if (mHasInputFilter) {
+ mHasInputFilter = false;
mWindowManagerService.setInputFilter(null);
- mIsTouchExplorationEnabled = false;
- sendTouchExplorationEnabledToClientsLocked();
}
}
@@ -1212,6 +1205,10 @@
| AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
| AccessibilityEvent.TYPE_VIEW_SCROLLED;
+ private static final int RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES =
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
+ | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT;
+
private int mRetrievalAlowingWindowId;
private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
@@ -1223,9 +1220,10 @@
public void updateRetrievalAllowingWindowAndEventSourceLocked(AccessibilityEvent event) {
final int windowId = event.getWindowId();
final int eventType = event.getEventType();
- if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) != 0) {
+ if ((eventType & RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES) != 0) {
mRetrievalAlowingWindowId = windowId;
- } else {
+ }
+ if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
event.setSource(null);
}
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 5a3a55d..0ad58d0 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -19,21 +19,21 @@
import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END;
import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START;
-import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
-import com.android.server.wm.InputFilter;
-
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.WindowManagerPolicy;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
+import android.view.ViewConfiguration;
+import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
+import com.android.server.wm.InputFilter;
+
import java.util.Arrays;
/**
@@ -146,6 +146,9 @@
// Command for delayed sending of a hover event.
private final SendHoverDelayed mSendHoverDelayed;
+ // Command for delayed sending of a long press.
+ private final PerformLongPressDelayed mPerformLongPressDelayed;
+
/**
* Creates a new instance.
*
@@ -160,6 +163,7 @@
mPointerTracker = new PointerTracker(context);
mHandler = new Handler(context.getMainLooper());
mSendHoverDelayed = new SendHoverDelayed();
+ mPerformLongPressDelayed = new PerformLongPressDelayed();
mAccessibilityManager = AccessibilityManager.getInstance(context);
}
@@ -208,15 +212,7 @@
final int activePointerCount = pointerTracker.getActivePointerCount();
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- // Send a hover for every finger down so the user gets feedback
- // where she is currently touching.
- mSendHoverDelayed.forceSendAndRemove();
- final int pointerIndex = event.getActionIndex();
- final int pointerIdBits = (1 << event.getPointerId(pointerIndex));
- mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits,
- policyFlags, DELAY_SEND_HOVER_MOVE);
- } break;
+ case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: {
switch (activePointerCount) {
case 0: {
@@ -224,13 +220,13 @@
+ "touch exploring state!");
}
case 1: {
- // Schedule a hover event which will lead to firing an
- // accessibility event from the hovered view.
- mSendHoverDelayed.remove();
+ // Send hover if pending.
+ mSendHoverDelayed.forceSendAndRemove();
+ // Send a hover for every finger down so the user gets feedback.
final int pointerId = pointerTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
final int lastAction = pointerTracker.getLastInjectedHoverAction();
- // If a schedules hover enter for another pointer is delivered we send move.
+ // If a hover enter for another pointer is delivered we send move.
final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER)
? MotionEvent.ACTION_HOVER_MOVE
: MotionEvent.ACTION_HOVER_ENTER;
@@ -244,7 +240,19 @@
// If more pointers down on the screen since the last touch
// exploration we discard the last cached touch explore event.
if (event.getPointerCount() != mLastTouchExploreEvent.getPointerCount()) {
- mLastTouchExploreEvent = null;
+ mLastTouchExploreEvent = null;
+ break;
+ }
+
+ // If the down is in the time slop => schedule a long press.
+ final long pointerDownTime =
+ pointerTracker.getReceivedPointerDownTime(pointerId);
+ final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
+ final long deltaTimeExplore = pointerDownTime - lastExploreTime;
+ if (deltaTimeExplore <= ACTIVATION_TIME_SLOP) {
+ mPerformLongPressDelayed.post(event, policyFlags,
+ ViewConfiguration.getLongPressTimeout());
+ break;
}
} break;
default: {
@@ -275,6 +283,7 @@
sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
// Make sure the scheduled down/move event is sent.
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// If we have transitioned to exploring state from another one
// we need to send a hover enter event here.
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
@@ -291,20 +300,11 @@
policyFlags);
}
- // Detect long press on the last touch explored position.
- if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null) {
+ // If the exploring pointer moved enough => cancel the long press.
+ if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null
+ && mPerformLongPressDelayed.isPenidng()) {
- // If the down was not in the time slop => nothing else to do.
- final long pointerDownTime =
- pointerTracker.getReceivedPointerDownTime(pointerId);
- final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
- final long deltaTimeExplore = pointerDownTime - lastExploreTime;
- if (deltaTimeExplore > ACTIVATION_TIME_SLOP) {
- mLastTouchExploreEvent = null;
- break;
- }
-
- // If the pointer moved more than the tap slop => nothing else to do.
+ // If the pointer moved more than the tap slop => cancel long press.
final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
- event.getX(pointerIndex);
final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
@@ -312,24 +312,14 @@
final float moveDelta = (float) Math.hypot(deltaX, deltaY);
if (moveDelta > mTouchExplorationTapSlop) {
mLastTouchExploreEvent = null;
+ mPerformLongPressDelayed.remove();
break;
}
-
- // If down for long enough we get a long press.
- final long deltaTimeMove = event.getEventTime() - pointerDownTime;
- if (deltaTimeMove > ViewConfiguration.getLongPressTimeout()) {
- mCurrentState = STATE_DELEGATING;
- // Make sure the scheduled hover exit is delivered.
- mSendHoverDelayed.forceSendAndRemove();
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
- sendMotionEvent(event, policyFlags);
- mTouchExploreGestureInProgress = false;
- mLastTouchExploreEvent = null;
- }
}
} break;
case 2: {
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -360,6 +350,7 @@
} break;
default: {
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -388,22 +379,26 @@
break;
}
+ mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
+
// If touch exploring announce the end of the gesture.
+ // Also do not click on the last explored location.
if (mTouchExploreGestureInProgress) {
- sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
mTouchExploreGestureInProgress = false;
+ mLastTouchExploreEvent = MotionEvent.obtain(event);
+ sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
+ break;
}
// Detect whether to activate i.e. click on the last explored location.
if (mLastTouchExploreEvent != null) {
-
// If the down was not in the time slop => nothing else to do.
final long eventTime =
pointerTracker.getLastReceivedUpPointerDownTime();
final long exploreTime = mLastTouchExploreEvent.getEventTime();
final long deltaTime = eventTime - exploreTime;
if (deltaTime > ACTIVATION_TIME_SLOP) {
- mSendHoverDelayed.forceSendAndRemove();
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -413,15 +408,14 @@
break;
}
- // If the pointer moved more than the tap slop => nothing else to do.
+ // If a tap is farther than the tap slop => nothing to do.
final int pointerIndex = event.findPointerIndex(pointerId);
- final float deltaX = pointerTracker.getLastReceivedUpPointerDownX()
+ final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
- event.getX(pointerIndex);
- final float deltaY = pointerTracker.getLastReceivedUpPointerDownY()
+ final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
- event.getY(pointerIndex);
final float deltaMove = (float) Math.hypot(deltaX, deltaY);
if (deltaMove > mTouchExplorationTapSlop) {
- mSendHoverDelayed.forceSendAndRemove();
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -432,7 +426,6 @@
}
// All preconditions are met, so click the last explored location.
- mSendHoverDelayed.forceSendAndRemove();
sendActionDownAndUp(mLastTouchExploreEvent, policyFlags);
mLastTouchExploreEvent = null;
} else {
@@ -448,6 +441,8 @@
}
} break;
case MotionEvent.ACTION_CANCEL: {
+ mSendHoverDelayed.remove();
+ mPerformLongPressDelayed.remove();
final int lastAction = pointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
final int pointerId = pointerTracker.getPrimaryActivePointerId();
@@ -934,8 +929,6 @@
private int mInjectedPointersDown;
// Keep track of the last up pointer data.
- private float mLastReceivedUpPointerDownX;
- private float mLastReveivedUpPointerDownY;
private long mLastReceivedUpPointerDownTime;
private int mLastReceivedUpPointerId;
private boolean mLastReceivedUpPointerActive;
@@ -968,8 +961,6 @@
mPrimaryActivePointerId = 0;
mHasMovingActivePointer = false;
mInjectedPointersDown = 0;
- mLastReceivedUpPointerDownX = 0;
- mLastReveivedUpPointerDownY = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerId = 0;
mLastReceivedUpPointerActive = false;
@@ -1126,20 +1117,6 @@
}
/**
- * @return The X coordinate where the last up received pointer went down.
- */
- public float getLastReceivedUpPointerDownX() {
- return mLastReceivedUpPointerDownX;
- }
-
- /**
- * @return The Y coordinate where the last up received pointer went down.
- */
- public float getLastReceivedUpPointerDownY() {
- return mLastReveivedUpPointerDownY;
- }
-
- /**
* @return The time when the last up received pointer went down.
*/
public long getLastReceivedUpPointerDownTime() {
@@ -1220,8 +1197,6 @@
final int pointerFlag = (1 << pointerId);
mLastReceivedUpPointerId = 0;
- mLastReceivedUpPointerDownX = 0;
- mLastReveivedUpPointerDownY = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerActive = false;
@@ -1262,8 +1237,6 @@
final int pointerFlag = (1 << pointerId);
mLastReceivedUpPointerId = pointerId;
- mLastReceivedUpPointerDownX = getReceivedPointerDownX(pointerId);
- mLastReveivedUpPointerDownY = getReceivedPointerDownY(pointerId);
mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
mLastReceivedUpPointerActive = isActivePointer(pointerId);
@@ -1400,6 +1373,51 @@
}
/**
+ * Class for delayed sending of long press.
+ */
+ private final class PerformLongPressDelayed implements Runnable {
+ private MotionEvent mEvent;
+ private int mPolicyFlags;
+
+ public void post(MotionEvent prototype, int policyFlags, long delay) {
+ mEvent = MotionEvent.obtain(prototype);
+ mPolicyFlags = policyFlags;
+ mHandler.postDelayed(this, delay);
+ }
+
+ public void remove() {
+ if (isPenidng()) {
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
+
+ private boolean isPenidng() {
+ return (mEvent != null);
+ }
+
+ @Override
+ public void run() {
+ mCurrentState = STATE_DELEGATING;
+ // Make sure the scheduled hover exit is delivered.
+ mSendHoverDelayed.forceSendAndRemove();
+ sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+ mTouchExploreGestureInProgress = false;
+ mLastTouchExploreEvent = null;
+ clear();
+ }
+
+ private void clear() {
+ if (!isPenidng()) {
+ return;
+ }
+ mEvent.recycle();
+ mEvent = null;
+ mPolicyFlags = 0;
+ }
+ }
+
+ /**
* Class for delayed sending of hover events.
*/
private final class SendHoverDelayed implements Runnable {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3389f33..66f88fc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1821,7 +1821,7 @@
// An application record is attached to a previous process,
// clean it up now.
if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
- handleAppDiedLocked(app, true);
+ handleAppDiedLocked(app, true, true);
}
}
@@ -2658,8 +2658,8 @@
* to the process.
*/
private final void handleAppDiedLocked(ProcessRecord app,
- boolean restarting) {
- cleanUpApplicationRecordLocked(app, restarting, -1);
+ boolean restarting, boolean allowRestart) {
+ cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1);
if (!restarting) {
mLruProcesses.remove(app);
}
@@ -2791,7 +2791,7 @@
TAG, "Dying app: " + app + ", pid: " + pid
+ ", thread: " + thread.asBinder());
boolean doLowMem = app.instrumentationClass == null;
- handleAppDiedLocked(app, false);
+ handleAppDiedLocked(app, false, true);
if (doLowMem) {
// If there are no longer any background processes running,
@@ -3195,7 +3195,7 @@
return;
}
killPackageProcessesLocked(packageName, pkgUid,
- SECONDARY_SERVER_ADJ, false, true);
+ SECONDARY_SERVER_ADJ, false, true, true);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -3358,7 +3358,7 @@
}
private final boolean killPackageProcessesLocked(String packageName, int uid,
- int minOomAdj, boolean callerWillRestart, boolean doit) {
+ int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
// Remove all processes this package may have touched: all with the
@@ -3369,6 +3369,10 @@
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
+ if (app.persistent) {
+ // we don't kill persistent processes
+ continue;
+ }
if (app.removed) {
if (doit) {
procs.add(app);
@@ -3389,7 +3393,7 @@
int N = procs.size();
for (int i=0; i<N; i++) {
- removeProcessLocked(procs.get(i), callerWillRestart);
+ removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
}
return N > 0;
}
@@ -3419,11 +3423,12 @@
}
boolean didSomething = killPackageProcessesLocked(name, uid, -100,
- callerWillRestart, doit);
+ callerWillRestart, false, doit);
for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
- if (r.packageName.equals(name)) {
+ if (r.packageName.equals(name)
+ && (r.app == null || !r.app.persistent)) {
if (!doit) {
return true;
}
@@ -3439,7 +3444,8 @@
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
for (ServiceRecord service : mServices.values()) {
- if (service.packageName.equals(name)) {
+ if (service.packageName.equals(name)
+ && (service.app == null || !service.app.persistent)) {
if (!doit) {
return true;
}
@@ -3471,7 +3477,8 @@
return didSomething;
}
- private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) {
+ private final boolean removeProcessLocked(ProcessRecord app,
+ boolean callerWillRestart, boolean allowRestart) {
final String name = app.processName;
final int uid = app.info.uid;
if (DEBUG_PROCESSES) Slog.d(
@@ -3490,7 +3497,7 @@
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
- handleAppDiedLocked(app, true);
+ handleAppDiedLocked(app, true, allowRestart);
mLruProcesses.remove(app);
Process.killProcess(pid);
@@ -3600,7 +3607,7 @@
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
- handleAppDiedLocked(app, true);
+ handleAppDiedLocked(app, true, true);
}
// Tell the process all about itself.
@@ -3783,7 +3790,7 @@
if (badApp) {
// todo: Also need to kill application to deal with all
// kinds of exceptions.
- handleAppDiedLocked(app, false);
+ handleAppDiedLocked(app, false, true);
return false;
}
@@ -6643,7 +6650,7 @@
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
- removeProcessLocked(proc, true);
+ removeProcessLocked(proc, true, false);
}
}
@@ -6826,10 +6833,6 @@
}
}
if (!app.persistent) {
- // Don't let services in this process be restarted and potentially
- // annoy the user repeatedly. Unless it is persistent, since those
- // processes run critical code.
- killServicesLocked(app, false);
// We don't want to start this process again until the user
// explicitly does so... but for persistent process, we really
// need to keep it running. If a persistent process is actually
@@ -6840,7 +6843,10 @@
app.bad = true;
mProcessCrashTimes.remove(app.info.processName, app.info.uid);
app.removed = true;
- removeProcessLocked(app, false);
+ // Don't let services in this process be restarted and potentially
+ // annoy the user repeatedly. Unless it is persistent, since those
+ // processes run critical code.
+ removeProcessLocked(app, false, false);
mMainStack.resumeTopActivityLocked(null);
return false;
}
@@ -9120,7 +9126,7 @@
// Should the service remain running? Note that in the
// extreme case of so many attempts to deliver a command
- // that it failed, that we also will stop it here.
+ // that it failed we also will stop it here.
if (sr.startRequested && (sr.stopIfKilled || canceled)) {
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
@@ -9189,7 +9195,7 @@
* a process when running in single process mode.
*/
private final void cleanUpApplicationRecordLocked(ProcessRecord app,
- boolean restarting, int index) {
+ boolean restarting, boolean allowRestart, int index) {
if (index >= 0) {
mLruProcesses.remove(index);
}
@@ -9221,7 +9227,7 @@
app.foregroundActivities = false;
app.hasShownUi = false;
- killServicesLocked(app, true);
+ killServicesLocked(app, allowRestart);
boolean restart = false;
@@ -9238,7 +9244,7 @@
// See if someone is waiting for this provider... in which
// case we don't remove it, but just let it restart.
int i = 0;
- if (!app.bad) {
+ if (!app.bad && allowRestart) {
for (; i<NL; i++) {
if (mLaunchingProviders.get(i) == cpr) {
restart = true;
@@ -9994,8 +10000,12 @@
while (it.hasNext()) {
ArrayList<ConnectionRecord> c = it.next();
for (int i=0; i<c.size(); i++) {
+ ConnectionRecord cr = c.get(i);
+ // There is still a connection to the service that is
+ // being brought down. Mark it as dead.
+ cr.serviceDead = true;
try {
- c.get(i).conn.connected(r.name, null);
+ cr.conn.connected(r.name, null);
} catch (Exception e) {
Slog.w(TAG, "Failure disconnecting service " + r.name +
" to connection " + c.get(i).conn.asBinder() +
@@ -10526,26 +10536,28 @@
b.intent.apps.remove(b.client);
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
- + ": shouldUnbind=" + b.intent.hasBound);
- if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
- && b.intent.hasBound) {
- try {
- bumpServiceExecutingLocked(s, "unbind");
- updateOomAdjLocked(s.app);
- b.intent.hasBound = false;
- // Assume the client doesn't want to know about a rebind;
- // we will deal with that later if it asks for one.
- b.intent.doRebind = false;
- s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
- } catch (Exception e) {
- Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
- serviceDoneExecutingLocked(s, true);
+ if (!c.serviceDead) {
+ if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
+ + ": shouldUnbind=" + b.intent.hasBound);
+ if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
+ && b.intent.hasBound) {
+ try {
+ bumpServiceExecutingLocked(s, "unbind");
+ updateOomAdjLocked(s.app);
+ b.intent.hasBound = false;
+ // Assume the client doesn't want to know about a rebind;
+ // we will deal with that later if it asks for one.
+ b.intent.doRebind = false;
+ s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+ serviceDoneExecutingLocked(s, true);
+ }
}
- }
-
- if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
- bringDownServiceLocked(s, false);
+
+ if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
+ bringDownServiceLocked(s, false);
+ }
}
}
@@ -12774,6 +12786,7 @@
}
if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
ProcessRecord client = cr.binding.client;
+ int clientAdj = adj;
int myHiddenAdj = hiddenAdj;
if (myHiddenAdj > client.hiddenAdj) {
if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
@@ -12782,8 +12795,35 @@
myHiddenAdj = VISIBLE_APP_ADJ;
}
}
- int clientAdj = computeOomAdjLocked(
+ clientAdj = computeOomAdjLocked(
client, myHiddenAdj, TOP_APP, true);
+ String adjType = null;
+ if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
+ // Not doing bind OOM management, so treat
+ // this guy more like a started service.
+ if (app.hasShownUi) {
+ // If this process has shown some UI, let it immediately
+ // go to the LRU list because it may be pretty heavy with
+ // UI stuff. We'll tag it with a label just to help
+ // debug and understand what is going on.
+ if (adj > clientAdj) {
+ adjType = "bound-bg-ui-services";
+ }
+ clientAdj = adj;
+ } else {
+ if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
+ // This service has not seen activity within
+ // recent memory, so allow it to drop to the
+ // LRU list if there is no other reason to keep
+ // it around. We'll also tag it with a label just
+ // to help debug and undertand what is going on.
+ if (adj > clientAdj) {
+ adjType = "bound-bg-services";
+ }
+ clientAdj = adj;
+ }
+ }
+ }
if (adj > clientAdj) {
adj = clientAdj >= VISIBLE_APP_ADJ
? clientAdj : VISIBLE_APP_ADJ;
@@ -12793,7 +12833,10 @@
if (client.keeping) {
app.keeping = true;
}
- app.adjType = "service";
+ adjType = "service";
+ }
+ if (adjType != null) {
+ app.adjType = adjType;
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
@@ -13413,7 +13456,7 @@
// Ignore exceptions.
}
}
- cleanUpApplicationRecordLocked(app, false, -1);
+ cleanUpApplicationRecordLocked(app, false, true, -1);
mRemovedProcesses.remove(i);
if (app.persistent) {
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 22acda9..0106114 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -32,6 +32,7 @@
final int clientLabel; // String resource labeling this client.
final PendingIntent clientIntent; // How to launch the client.
String stringName; // Caching of toString.
+ boolean serviceDead; // Well is it?
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "binding=" + binding);
@@ -61,6 +62,9 @@
sb.append("ConnectionRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
+ if (serviceDead) {
+ sb.append("DEAD ");
+ }
sb.append(binding.service.shortName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index a5a6d8e..ae8b89d 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -202,7 +202,11 @@
sm.start();
}
} else {
- if (sm != null) {
+ if (isUsb(iface)) {
+ // ignore usb0 down after enabling RNDIS
+ // we will handle disconnect in interfaceRemoved instead
+ Log.d(TAG, "ignoring interface down for " + iface);
+ } else if (sm != null) {
sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
mIfaces.remove(iface);
}
@@ -237,6 +241,7 @@
}
public void interfaceAdded(String iface) {
+ if (DEBUG) Log.d(TAG, "interfaceAdded " + iface);
boolean found = false;
boolean usb = false;
if (isWifi(iface)) {
@@ -268,6 +273,7 @@
}
public void interfaceRemoved(String iface) {
+ if (DEBUG) Log.d(TAG, "interfaceRemoved " + iface);
synchronized (mIfaces) {
TetherInterfaceSM sm = mIfaces.get(iface);
if (sm == null) {
@@ -371,7 +377,8 @@
}
}
Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
- broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
availableList);
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
@@ -542,6 +549,7 @@
}
public int setUsbTethering(boolean enable) {
+ if (DEBUG) Log.d(TAG, "setUsbTethering(" + enable + ")");
UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
synchronized (this) {
diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java
index e3131fe..b38ea13 100644
--- a/services/java/com/android/server/location/GeocoderProxy.java
+++ b/services/java/com/android/server/location/GeocoderProxy.java
@@ -47,7 +47,9 @@
public GeocoderProxy(Context context, String serviceName) {
mContext = context;
mIntent = new Intent(serviceName);
- mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ mContext.bindService(mIntent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALLOW_OOM_MANAGEMENT);
}
/**
@@ -58,7 +60,9 @@
synchronized (mMutex) {
mContext.unbindService(mServiceConnection);
mServiceConnection = new Connection();
- mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ mContext.bindService(mIntent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALLOW_OOM_MANAGEMENT);
}
}
@@ -67,14 +71,12 @@
private IGeocodeProvider mProvider;
public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "onServiceConnected " + className);
synchronized (this) {
mProvider = IGeocodeProvider.Stub.asInterface(service);
}
}
public void onServiceDisconnected(ComponentName className) {
- Log.d(TAG, "onServiceDisconnected " + className);
synchronized (this) {
mProvider = null;
}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index c813d37..b79e31f 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -256,6 +256,7 @@
private String mAGpsApn;
private int mAGpsDataConnectionState;
+ private int mAGpsDataConnectionIpAddr;
private final ConnectivityManager mConnMgr;
private final GpsNetInitiatedHandler mNIHandler;
@@ -495,8 +496,21 @@
if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
&& mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
String apnName = info.getExtraInfo();
- if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
+ if (mNetworkAvailable) {
+ if (apnName == null) {
+ /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
+ exception in the following call to native_agps_data_conn_open*/
+ apnName = "dummy-apn";
+ }
mAGpsApn = apnName;
+ if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
+ if (mAGpsDataConnectionIpAddr != 0xffffffff) {
+ boolean route_result;
+ if (DEBUG) Log.d(TAG, "call requestRouteToHost");
+ route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
+ mAGpsDataConnectionIpAddr);
+ if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
+ }
if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
native_agps_data_conn_open(apnName);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
@@ -1231,7 +1245,7 @@
/**
* called from native code to update AGPS status
*/
- private void reportAGpsStatus(int type, int status) {
+ private void reportAGpsStatus(int type, int status, int ipaddr) {
switch (status) {
case GPS_REQUEST_AGPS_DATA_CONN:
if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
@@ -1240,9 +1254,19 @@
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
int result = mConnMgr.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
+ mAGpsDataConnectionIpAddr = ipaddr;
if (result == Phone.APN_ALREADY_ACTIVE) {
if (DEBUG) Log.d(TAG, "Phone.APN_ALREADY_ACTIVE");
if (mAGpsApn != null) {
+ Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
+ if (mAGpsDataConnectionIpAddr != 0xffffffff) {
+ boolean route_result;
+ if (DEBUG) Log.d(TAG, "call requestRouteToHost");
+ route_result = mConnMgr.requestRouteToHost(
+ ConnectivityManager.TYPE_MOBILE_SUPL,
+ mAGpsDataConnectionIpAddr);
+ if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
+ }
native_agps_data_conn_open(mAGpsApn);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else {
diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java
index 1a1a170..0bc1664 100644
--- a/services/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/java/com/android/server/location/LocationProviderProxy.java
@@ -28,7 +28,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.WorkSource;
import android.util.Log;
@@ -65,7 +64,9 @@
mName = name;
mIntent = new Intent(serviceName);
mHandler = handler;
- mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ mContext.bindService(mIntent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALLOW_OOM_MANAGEMENT);
}
/**
@@ -76,7 +77,9 @@
synchronized (mMutex) {
mContext.unbindService(mServiceConnection);
mServiceConnection = new Connection();
- mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ mContext.bindService(mIntent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALLOW_OOM_MANAGEMENT);
}
}
@@ -88,7 +91,6 @@
private DummyLocationProvider mCachedAttributes; // synchronized by mMutex
public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className);
synchronized (this) {
mProvider = ILocationProvider.Stub.asInterface(service);
if (mProvider != null) {
@@ -98,7 +100,6 @@
}
public void onServiceDisconnected(ComponentName className) {
- Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className);
synchronized (this) {
mProvider = null;
}
diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java
new file mode 100644
index 0000000..0d1c3b2
--- /dev/null
+++ b/services/java/com/android/server/net/NetworkAlertObserver.java
@@ -0,0 +1,44 @@
+/*
+ * 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.INetworkManagementEventObserver;
+
+/**
+ * @hide
+ */
+public abstract class NetworkAlertObserver extends INetworkManagementEventObserver.Stub {
+ @Override
+ public void interfaceStatusChanged(String iface, boolean up) {
+ // ignored; interface changes come through ConnectivityService
+ }
+
+ @Override
+ public void interfaceRemoved(String iface) {
+ // ignored; interface changes come through ConnectivityService
+ }
+
+ @Override
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ // ignored; interface changes come through ConnectivityService
+ }
+
+ @Override
+ public void interfaceAdded(String iface) {
+ // ignored; interface changes come through ConnectivityService
+ }
+}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 435c394..756cd00 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -25,13 +25,11 @@
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
-import static android.net.ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
+import static android.net.NetworkPolicy.SNOOZE_NEVER;
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_METERED_BACKGROUND;
@@ -46,6 +44,12 @@
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
+import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -56,6 +60,7 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -64,6 +69,7 @@
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
@@ -131,25 +137,31 @@
private static final boolean LOGD = true;
private static final boolean LOGV = false;
- private static final int VERSION_CURRENT = 1;
+ private static final int VERSION_INIT = 1;
+ private static final int VERSION_ADDED_SNOOZE = 2;
+ private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
- private static final int TYPE_WARNING = 0x1;
- private static final int TYPE_LIMIT = 0x2;
+ // @VisibleForTesting
+ public static final int TYPE_WARNING = 0x1;
+ public static final int TYPE_LIMIT = 0x2;
+ public static final int TYPE_LIMIT_SNOOZED = 0x3;
private static final String TAG_POLICY_LIST = "policy-list";
private static final String TAG_NETWORK_POLICY = "network-policy";
private static final String TAG_UID_POLICY = "uid-policy";
private static final String ATTR_VERSION = "version";
+ private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
private static final String ATTR_CYCLE_DAY = "cycleDay";
private static final String ATTR_WARNING_BYTES = "warningBytes";
private static final String ATTR_LIMIT_BYTES = "limitBytes";
+ private static final String ATTR_LAST_SNOOZE = "lastSnooze";
private static final String ATTR_UID = "uid";
private static final String ATTR_POLICY = "policy";
@@ -162,7 +174,7 @@
private final IActivityManager mActivityManager;
private final IPowerManager mPowerManager;
private final INetworkStatsService mNetworkStats;
- private final INetworkManagementService mNetworkManagement;
+ private final INetworkManagementService mNetworkManager;
private final TrustedTime mTime;
private IConnectivityManager mConnManager;
@@ -171,20 +183,22 @@
private final Object mRulesLock = new Object();
private boolean mScreenOn;
- private boolean mBackgroundData;
+ private boolean mRestrictBackground;
- /** Current policy for network templates. */
- private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList();
- /** Current derived network rules for ifaces. */
+ /** Defined network policies. */
+ private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
+ /** Currently active network rules for ifaces. */
private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
- /** Current policy for each UID. */
+ /** Defined UID policies. */
private SparseIntArray mUidPolicy = new SparseIntArray();
- /** Current derived rules for each UID. */
+ /** Currently derived rules for each UID. */
private SparseIntArray mUidRules = new SparseIntArray();
/** Set of ifaces that are metered. */
private HashSet<String> mMeteredIfaces = Sets.newHashSet();
+ /** Set of over-limit templates that have been notified. */
+ private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
/** Foreground at both UID and PID granularity. */
private SparseBooleanArray mUidForeground = new SparseBooleanArray();
@@ -202,6 +216,8 @@
// TODO: keep whitelist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs.
+ // TODO: migrate notifications to SystemUI
+
public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
IPowerManager powerManager, INetworkStatsService networkStats,
INetworkManagementService networkManagement) {
@@ -221,7 +237,7 @@
mActivityManager = checkNotNull(activityManager, "missing activityManager");
mPowerManager = checkNotNull(powerManager, "missing powerManager");
mNetworkStats = checkNotNull(networkStats, "missing networkStats");
- mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement");
+ mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
mTime = checkNotNull(time, "missing TrustedTime");
mHandlerThread = new HandlerThread(TAG);
@@ -243,10 +259,13 @@
synchronized (mRulesLock) {
// read policy from disk
readPolicyLocked();
+
+ if (mRestrictBackground) {
+ updateRulesForRestrictBackgroundLocked();
+ }
}
updateScreenOn();
- updateBackgroundData(true);
try {
mActivityManager.registerProcessObserver(mProcessObserver);
@@ -256,13 +275,21 @@
Slog.e(TAG, "unable to register IProcessObserver", e);
}
+ try {
+ mNetworkManager.registerObserver(mAlertObserver);
+ } catch (RemoteException e) {
+ // ouch, no alert updates means we fall back to
+ // ACTION_NETWORK_STATS_UPDATED broadcasts.
+ Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
+ }
+
// TODO: traverse existing processes to know foreground state, or have
// activitymanager dispatch current state when new observer attached.
final IntentFilter screenFilter = new IntentFilter();
screenFilter.addAction(Intent.ACTION_SCREEN_ON);
screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mContext.registerReceiver(mScreenReceiver, screenFilter);
+ mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
// watch for network interfaces to be claimed
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
@@ -272,7 +299,6 @@
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
packageFilter.addAction(ACTION_UID_REMOVED);
- packageFilter.addDataScheme("package");
mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
// listen for stats update events
@@ -280,10 +306,6 @@
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() {
@@ -377,17 +399,26 @@
};
/**
- * Receiver that watches for
- * {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}.
+ * Observer that watches for {@link INetworkManagementService} alerts.
*/
- private BroadcastReceiver mBgReceiver = new BroadcastReceiver() {
+ private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
@Override
- public void onReceive(Context context, Intent intent) {
- // on background handler thread, and verified CONNECTIVITY_INTERNAL
- // permission above.
+ public void limitReached(String limitName, String iface) {
+ // only someone like NMS should be calling us
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
synchronized (mRulesLock) {
- updateBackgroundData(false);
+ if (mMeteredIfaces.contains(iface)) {
+ try {
+ // force stats update to make sure we have numbers that
+ // caused alert to trigger.
+ mNetworkStats.forceUpdate();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "problem updating network stats");
+ }
+
+ updateNotificationsLocked();
+ }
}
}
};
@@ -415,42 +446,69 @@
final long start = computeLastCycleBoundary(currentTime, policy);
final long end = currentTime;
- final long total;
+ final long totalBytes;
try {
final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
policy.template, start, end);
final NetworkStats.Entry entry = stats.getValues(0, null);
- total = entry.rxBytes + entry.txBytes;
+ totalBytes = entry.rxBytes + entry.txBytes;
} catch (RemoteException e) {
Slog.w(TAG, "problem reading summary for template " + policy.template);
continue;
}
- if (policy.limitBytes != LIMIT_DISABLED && total >= policy.limitBytes) {
+ if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
cancelNotification(policy, TYPE_WARNING);
- enqueueNotification(policy, TYPE_LIMIT);
+
+ if (policy.lastSnooze >= start) {
+ cancelNotification(policy, TYPE_LIMIT);
+ enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
+ } else {
+ cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+ enqueueNotification(policy, TYPE_LIMIT, totalBytes);
+ notifyOverLimitLocked(policy.template);
+ }
+
} else {
cancelNotification(policy, TYPE_LIMIT);
+ cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+ notifyUnderLimitLocked(policy.template);
- if (policy.warningBytes != WARNING_DISABLED && total >= policy.warningBytes) {
- enqueueNotification(policy, TYPE_WARNING);
+ if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
+ enqueueNotification(policy, TYPE_WARNING, totalBytes);
} else {
cancelNotification(policy, TYPE_WARNING);
}
}
-
}
// clear notifications for non-active policies
- for (NetworkPolicy policy : mNetworkPolicy) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
if (!mNetworkRules.containsKey(policy)) {
cancelNotification(policy, TYPE_WARNING);
cancelNotification(policy, TYPE_LIMIT);
+ cancelNotification(policy, TYPE_LIMIT_SNOOZED);
+ notifyUnderLimitLocked(policy.template);
}
}
}
/**
+ * Notify that given {@link NetworkTemplate} is over
+ * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
+ */
+ private void notifyOverLimitLocked(NetworkTemplate template) {
+ if (!mOverLimitNotified.contains(template)) {
+ mContext.startActivity(buildNetworkOverLimitIntent(template));
+ mOverLimitNotified.add(template);
+ }
+ }
+
+ private void notifyUnderLimitLocked(NetworkTemplate template) {
+ mOverLimitNotified.remove(template);
+ }
+
+ /**
* Build unique tag that identifies an active {@link NetworkPolicy}
* notification of a specific type, like {@link #TYPE_LIMIT}.
*/
@@ -462,7 +520,7 @@
* Show notification for combined {@link NetworkPolicy} and specific type,
* like {@link #TYPE_LIMIT}. Okay to call multiple times.
*/
- private void enqueueNotification(NetworkPolicy policy, int type) {
+ private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
final String tag = buildNotificationTag(policy, type);
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setOnlyAlertOnce(true);
@@ -471,8 +529,8 @@
final Resources res = mContext.getResources();
switch (type) {
case TYPE_WARNING: {
- final String title = res.getString(R.string.data_usage_warning_title);
- final String body = res.getString(R.string.data_usage_warning_body,
+ final CharSequence title = res.getText(R.string.data_usage_warning_title);
+ final CharSequence body = res.getString(R.string.data_usage_warning_body,
Formatter.formatFileSize(mContext, policy.warningBytes));
builder.setSmallIcon(R.drawable.ic_menu_info_details);
@@ -480,25 +538,24 @@
builder.setContentTitle(title);
builder.setContentText(body);
- final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
+ final Intent intent = buildViewDataUsageIntent(policy.template);
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
}
case TYPE_LIMIT: {
- final String title;
- final String body = res.getString(R.string.data_usage_limit_body);
+ final CharSequence body = res.getText(R.string.data_usage_limit_body);
+
+ final CharSequence title;
switch (policy.template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
- title = res.getString(R.string.data_usage_3g_limit_title);
+ title = res.getText(R.string.data_usage_3g_limit_title);
break;
case MATCH_MOBILE_4G:
- title = res.getString(R.string.data_usage_4g_limit_title);
+ title = res.getText(R.string.data_usage_4g_limit_title);
break;
default:
- title = res.getString(R.string.data_usage_mobile_limit_title);
+ title = res.getText(R.string.data_usage_mobile_limit_title);
break;
}
@@ -507,9 +564,35 @@
builder.setContentTitle(title);
builder.setContentText(body);
- final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule());
+ final Intent intent = buildNetworkOverLimitIntent(policy.template);
+ builder.setContentIntent(PendingIntent.getActivity(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ break;
+ }
+ case TYPE_LIMIT_SNOOZED: {
+ final long overBytes = totalBytes - policy.limitBytes;
+ final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
+ Formatter.formatFileSize(mContext, overBytes));
+
+ final CharSequence title;
+ switch (policy.template.getMatchRule()) {
+ case MATCH_MOBILE_3G_LOWER:
+ title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
+ break;
+ case MATCH_MOBILE_4G:
+ title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
+ break;
+ default:
+ title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
+ break;
+ }
+
+ builder.setSmallIcon(R.drawable.ic_menu_info_details);
+ builder.setTicker(title);
+ builder.setContentTitle(title);
+ builder.setContentText(body);
+
+ final Intent intent = buildViewDataUsageIntent(policy.template);
builder.setContentIntent(PendingIntent.getActivity(
mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
break;
@@ -591,7 +674,7 @@
// build list of rules and ifaces to enforce them against
mNetworkRules.clear();
final ArrayList<String> ifaceList = Lists.newArrayList();
- for (NetworkPolicy policy : mNetworkPolicy) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
// collect all active ifaces that match this template
ifaceList.clear();
@@ -642,11 +725,18 @@
+ Arrays.toString(ifaces));
}
- // TODO: register for warning notification trigger through NMS
+ final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
+ final boolean hasWarning = policy.warningBytes != WARNING_DISABLED;
- if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
- // remaining "quota" is based on usage in current cycle
- final long quota = Math.max(0, policy.limitBytes - total);
+ if (hasLimit || hasWarning) {
+ final long quotaBytes;
+ if (hasLimit) {
+ // remaining "quota" is based on usage in current cycle
+ quotaBytes = Math.max(0, policy.limitBytes - total);
+ } else {
+ // to track warning alert later, use a high quota
+ quotaBytes = Long.MAX_VALUE;
+ }
if (ifaces.length > 1) {
// TODO: switch to shared quota once NMS supports
@@ -655,8 +745,20 @@
for (String iface : ifaces) {
removeInterfaceQuota(iface);
- setInterfaceQuota(iface, quota);
- newMeteredIfaces.add(iface);
+ if (quotaBytes > 0) {
+ setInterfaceQuota(iface, quotaBytes);
+ newMeteredIfaces.add(iface);
+ }
+ }
+ }
+
+ if (hasWarning) {
+ final long alertBytes = Math.max(0, policy.warningBytes - total);
+ for (String iface : ifaces) {
+ removeInterfaceAlert(iface);
+ if (alertBytes > 0) {
+ setInterfaceAlert(iface, alertBytes);
+ }
}
}
}
@@ -685,7 +787,7 @@
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
- for (NetworkPolicy policy : mNetworkPolicy) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
if (policy.template.matches(probeIdent)) {
mobileDefined = true;
}
@@ -704,7 +806,8 @@
final int cycleDay = time.monthDay;
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
- mNetworkPolicy.add(new NetworkPolicy(template, cycleDay, warningBytes, LIMIT_DISABLED));
+ mNetworkPolicy.put(template, new NetworkPolicy(
+ template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
writePolicyLocked();
}
}
@@ -723,12 +826,22 @@
in.setInput(fis, null);
int type;
- int version = VERSION_CURRENT;
+ int version = VERSION_INIT;
while ((type = in.next()) != END_DOCUMENT) {
final String tag = in.getName();
if (type == START_TAG) {
if (TAG_POLICY_LIST.equals(tag)) {
version = readIntAttribute(in, ATTR_VERSION);
+ if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
+ mRestrictBackground = readBooleanAttribute(
+ in, ATTR_RESTRICT_BACKGROUND);
+ } else {
+ try {
+ mRestrictBackground = !mConnManager.getBackgroundDataSetting();
+ } catch (RemoteException e) {
+ mRestrictBackground = false;
+ }
+ }
} else if (TAG_NETWORK_POLICY.equals(tag)) {
final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
@@ -736,11 +849,17 @@
final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
+ final long lastSnooze;
+ if (version >= VERSION_ADDED_SNOOZE) {
+ lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
+ } else {
+ lastSnooze = SNOOZE_NEVER;
+ }
final NetworkTemplate template = new NetworkTemplate(
networkTemplate, subscriberId);
- mNetworkPolicy.add(
- new NetworkPolicy(template, cycleDay, warningBytes, limitBytes));
+ mNetworkPolicy.put(template, new NetworkPolicy(
+ template, cycleDay, warningBytes, limitBytes, lastSnooze));
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
@@ -778,10 +897,11 @@
out.startDocument(null, true);
out.startTag(null, TAG_POLICY_LIST);
- writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND);
+ writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
// write all known network policies
- for (NetworkPolicy policy : mNetworkPolicy) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
final NetworkTemplate template = policy.template;
out.startTag(null, TAG_NETWORK_POLICY);
@@ -793,6 +913,7 @@
writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
+ writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
out.endTag(null, TAG_NETWORK_POLICY);
}
@@ -880,7 +1001,7 @@
synchronized (mRulesLock) {
mNetworkPolicy.clear();
for (NetworkPolicy policy : policies) {
- mNetworkPolicy.add(policy);
+ mNetworkPolicy.put(policy.template, policy);
}
updateNetworkRulesLocked();
@@ -895,7 +1016,53 @@
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
synchronized (mRulesLock) {
- return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]);
+ return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
+ }
+ }
+
+ @Override
+ public void snoozePolicy(NetworkTemplate template) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ // try refreshing time source when stale
+ if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
+ mTime.forceRefresh();
+ }
+
+ final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
+ : System.currentTimeMillis();
+
+ synchronized (mRulesLock) {
+ // find and snooze local policy that matches
+ final NetworkPolicy policy = mNetworkPolicy.get(template);
+ if (policy == null) {
+ throw new IllegalArgumentException("unable to find policy for " + template);
+ }
+
+ policy.lastSnooze = currentTime;
+
+ updateNetworkRulesLocked();
+ updateNotificationsLocked();
+ writePolicyLocked();
+ }
+ }
+
+ @Override
+ public void setRestrictBackground(boolean restrictBackground) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mRulesLock) {
+ mRestrictBackground = restrictBackground;
+ updateRulesForRestrictBackgroundLocked();
+ }
+ }
+
+ @Override
+ public boolean getRestrictBackground() {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mRulesLock) {
+ return mRestrictBackground;
}
}
@@ -903,9 +1070,24 @@
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+ final HashSet<String> argSet = new HashSet<String>();
+ for (String arg : args) {
+ argSet.add(arg);
+ }
+
synchronized (mRulesLock) {
+ if (argSet.contains("unsnooze")) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
+ policy.lastSnooze = SNOOZE_NEVER;
+ }
+ writePolicyLocked();
+ fout.println("Wiped snooze timestamps");
+ return;
+ }
+
+ fout.print("Restrict background: "); fout.println(mRestrictBackground);
fout.println("Network policies:");
- for (NetworkPolicy policy : mNetworkPolicy) {
+ for (NetworkPolicy policy : mNetworkPolicy.values()) {
fout.print(" "); fout.println(policy.toString());
}
@@ -996,21 +1178,6 @@
}
}
- 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.
*/
@@ -1026,9 +1193,9 @@
}
/**
- * Update rules that might be changed by {@link #mBackgroundData} value.
+ * Update rules that might be changed by {@link #mRestrictBackground} value.
*/
- private void updateRulesForBackgroundDataLocked() {
+ private void updateRulesForRestrictBackgroundLocked() {
// update rules for all installed applications
final PackageManager pm = mContext.getPackageManager();
final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
@@ -1062,7 +1229,7 @@
// uid in background, and policy says to block metered data
uidRules = RULE_REJECT_METERED;
}
- if (!uidForeground && !mBackgroundData) {
+ if (!uidForeground && mRestrictBackground) {
// uid in background, and global background disabled
uidRules = RULE_REJECT_METERED;
}
@@ -1124,9 +1291,9 @@
}
};
- private void setInterfaceQuota(String iface, long quota) {
+ private void setInterfaceQuota(String iface, long quotaBytes) {
try {
- mNetworkManagement.setInterfaceQuota(iface, quota);
+ mNetworkManager.setInterfaceQuota(iface, quotaBytes);
} catch (IllegalStateException e) {
Slog.e(TAG, "problem setting interface quota", e);
} catch (RemoteException e) {
@@ -1136,7 +1303,7 @@
private void removeInterfaceQuota(String iface) {
try {
- mNetworkManagement.removeInterfaceQuota(iface);
+ mNetworkManager.removeInterfaceQuota(iface);
} catch (IllegalStateException e) {
Slog.e(TAG, "problem removing interface quota", e);
} catch (RemoteException e) {
@@ -1144,9 +1311,29 @@
}
}
+ private void setInterfaceAlert(String iface, long alertBytes) {
+ try {
+ mNetworkManager.setInterfaceAlert(iface, alertBytes);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem setting interface alert", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem setting interface alert", e);
+ }
+ }
+
+ private void removeInterfaceAlert(String iface) {
+ try {
+ mNetworkManager.removeInterfaceAlert(iface);
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem removing interface alert", e);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "problem removing interface alert", e);
+ }
+ }
+
private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
try {
- mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
} catch (IllegalStateException e) {
Slog.e(TAG, "problem setting uid rules", e);
} catch (RemoteException e) {
@@ -1160,6 +1347,24 @@
return telephony.getSubscriberId();
}
+ private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
+ final Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+ return intent;
+ }
+
+ private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
+ final Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+ return intent;
+ }
+
private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
final int size = source.size();
for (int i = 0; i < size; i++) {
@@ -1184,32 +1389,43 @@
fout.print("]");
}
- private static int readIntAttribute(XmlPullParser in, String name) throws IOException {
- final String value = in.getAttributeValue(null, name);
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
+ public static class XmlUtils {
+ public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
+ final String value = in.getAttributeValue(null, name);
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
+ }
+ }
+
+ public static void writeIntAttribute(XmlSerializer out, String name, int value)
+ throws IOException {
+ out.attribute(null, name, Integer.toString(value));
+ }
+
+ public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
+ final String value = in.getAttributeValue(null, name);
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
+ }
+ }
+
+ public static void writeLongAttribute(XmlSerializer out, String name, long value)
+ throws IOException {
+ out.attribute(null, name, Long.toString(value));
+ }
+
+ public static boolean readBooleanAttribute(XmlPullParser in, String name) {
+ final String value = in.getAttributeValue(null, name);
+ return Boolean.parseBoolean(value);
+ }
+
+ public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
+ throws IOException {
+ out.attribute(null, name, Boolean.toString(value));
}
}
-
- private static long readLongAttribute(XmlPullParser in, String name) throws IOException {
- final String value = in.getAttributeValue(null, name);
- try {
- return Long.parseLong(value);
- } catch (NumberFormatException e) {
- throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
- }
- }
-
- private static void writeIntAttribute(XmlSerializer out, String name, int value)
- throws IOException {
- out.attribute(null, name, Integer.toString(value));
- }
-
- private static void writeLongAttribute(XmlSerializer out, String name, long value)
- throws IOException {
- out.attribute(null, name, Long.toString(value));
- }
-
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index d6a15e6..88e0fa8 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -20,6 +20,7 @@
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 static libcore.io.OsConstants.S_ISLNK;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
@@ -76,6 +77,7 @@
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.FileUtils.FileStatus;
+import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -128,6 +130,9 @@
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
/**
* Keep track of all those .apks everywhere.
*
@@ -2860,8 +2865,17 @@
}
private File getDataPathForPackage(String packageName, int userId) {
- return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
+ /*
+ * Until we fully support multiple users, return the directory we
+ * previously would have. The PackageManagerTests will need to be
+ * revised when this is changed back..
+ */
+ if (userId == 0) {
+ return new File(mAppDataDir, packageName);
+ } else {
+ return new File(mUserAppDataDir.getAbsolutePath() + File.separator + userId
+ File.separator + packageName);
+ }
}
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
@@ -3329,16 +3343,27 @@
} else if (nativeLibraryDir.getCanonicalFile().getParent()
.equals(dataPathString)) {
/*
+ * Make sure the native library dir isn't a symlink to
+ * something. If it is, ask installd to remove it and create
+ * a directory so we can copy to it afterwards.
+ */
+ boolean isSymLink;
+ try {
+ isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode);
+ } catch (ErrnoException e) {
+ // This shouldn't happen, but we'll fail-safe.
+ isSymLink = true;
+ }
+ if (isSymLink) {
+ mInstaller.unlinkNativeLibraryDirectory(dataPathString);
+ }
+
+ /*
* If this is an internal application or our
* nativeLibraryPath points to our data directory, unpack
- * the libraries. The native library path pointing to the
- * data directory for an application in an ASEC container
- * can happen for older apps that existed before an OTA to
- * Gingerbread.
+ * the libraries if necessary.
*/
- Slog.i(TAG, "Unpacking native libraries for " + path);
- mInstaller.unlinkNativeLibraryDirectory(dataPathString);
- NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir);
+ NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
} else {
Slog.i(TAG, "Linking native library dir for " + path);
mInstaller.linkNativeLibraryDirectory(dataPathString,
@@ -7921,7 +7946,7 @@
.unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) {
returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
} else {
- NativeLibraryHelper.copyNativeBinariesLI(new File(
+ NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File(
newCodePath), new File(newNativePath));
}
} else {
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index f183f83..11cb555 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -528,10 +528,10 @@
private void updateUsbNotification() {
if (mNotificationManager == null || !mUseUsbNotification) return;
+ int id = NOTIFICATION_NONE;
+ Resources r = mContext.getResources();
+ CharSequence title = null;
if (mConnected) {
- Resources r = mContext.getResources();
- CharSequence title = null;
- int id = NOTIFICATION_NONE;
if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) {
title = r.getText(
com.android.internal.R.string.usb_mtp_notification_title);
@@ -550,16 +550,19 @@
com.android.internal.R.string.usb_accessory_notification_title);
id = NOTIFICATION_ACCESSORY;
} else {
- Slog.e(TAG, "No known USB function in updateUsbNotification");
- }
- if (id != mUsbNotificationId) {
- // clear notification if title needs changing
- if (mUsbNotificationId != NOTIFICATION_NONE) {
- mNotificationManager.cancel(mUsbNotificationId);
- mUsbNotificationId = NOTIFICATION_NONE;
+ // There is a different notification for USB tethering so we don't need one here
+ if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) {
+ Slog.e(TAG, "No known USB function in updateUsbNotification");
}
}
- if (mUsbNotificationId == NOTIFICATION_NONE) {
+ }
+ if (id != mUsbNotificationId) {
+ // clear notification if title needs changing
+ if (mUsbNotificationId != NOTIFICATION_NONE) {
+ mNotificationManager.cancel(mUsbNotificationId);
+ mUsbNotificationId = NOTIFICATION_NONE;
+ }
+ if (id != NOTIFICATION_NONE) {
CharSequence message = r.getText(
com.android.internal.R.string.usb_notification_message);
@@ -584,10 +587,6 @@
mNotificationManager.notify(id, notification);
mUsbNotificationId = id;
}
-
- } else if (mUsbNotificationId != NOTIFICATION_NONE) {
- mNotificationManager.cancel(mUsbNotificationId);
- mUsbNotificationId = NOTIFICATION_NONE;
}
}
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 8146fca..b37d1c2 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -123,8 +123,8 @@
// The drag window covers the entire display
mDragWindowHandle.frameLeft = 0;
mDragWindowHandle.frameTop = 0;
- mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth();
- mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight();
+ mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
+ mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
}
}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 3133a19..1d0857b 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -64,7 +64,8 @@
private static native void nativeInit(Context context,
Callbacks callbacks, MessageQueue messageQueue);
private static native void nativeStart();
- private static native void nativeSetDisplaySize(int displayId, int width, int height);
+ private static native void nativeSetDisplaySize(int displayId, int width, int height,
+ int externalWidth, int externalHeight);
private static native void nativeSetDisplayOrientation(int displayId, int rotation);
private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
@@ -144,15 +145,17 @@
updatePointerSpeedFromSettings();
}
- public void setDisplaySize(int displayId, int width, int height) {
- if (width <= 0 || height <= 0) {
+ public void setDisplaySize(int displayId, int width, int height,
+ int externalWidth, int externalHeight) {
+ if (width <= 0 || height <= 0 || externalWidth <= 0 || externalHeight <= 0) {
throw new IllegalArgumentException("Invalid display id or dimensions.");
}
if (DEBUG) {
- Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height);
+ Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height
+ + " external size " + externalWidth + "x" + externalHeight);
}
- nativeSetDisplaySize(displayId, width, height);
+ nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight);
}
public void setDisplayOrientation(int displayId, int rotation) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 8470918..16af151 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -25,9 +25,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.util.DisplayMetrics;
import android.util.Slog;
-import android.view.Display;
import android.view.Surface;
import android.view.SurfaceSession;
import android.view.animation.Animation;
@@ -41,7 +39,6 @@
static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
final Context mContext;
- final Display mDisplay;
Surface mSurface;
BlackFrame mBlackFrame;
int mWidth, mHeight;
@@ -58,18 +55,14 @@
final Transformation mEnterTransformation = new Transformation();
boolean mStarted;
- final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
final Matrix mSnapshotInitialMatrix = new Matrix();
final Matrix mSnapshotFinalMatrix = new Matrix();
final Matrix mTmpMatrix = new Matrix();
final float[] mTmpFloats = new float[9];
- public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
- boolean inTransaction) {
+ public ScreenRotationAnimation(Context context, SurfaceSession session,
+ boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
mContext = context;
- mDisplay = display;
-
- display.getRealMetrics(mDisplayMetrics);
Bitmap screenshot = Surface.screenshot(0, 0);
@@ -83,9 +76,9 @@
mWidth = screenshot.getWidth();
mHeight = screenshot.getHeight();
- mOriginalRotation = display.getRotation();
- mOriginalWidth = mDisplayMetrics.widthPixels;
- mOriginalHeight = mDisplayMetrics.heightPixels;
+ mOriginalRotation = originalRotation;
+ mOriginalWidth = originalWidth;
+ mOriginalHeight = originalHeight;
if (!inTransaction) {
if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
@@ -106,7 +99,7 @@
WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
" FREEZE " + mSurface + ": CREATE");
- setRotation(display.getRotation());
+ setRotation(originalRotation);
if (mSurface != null) {
Rect dirty = new Rect(0, 0, mWidth, mHeight);
@@ -212,7 +205,7 @@
* Returns true if animating.
*/
public boolean dismiss(SurfaceSession session, long maxAnimationDuration,
- float animationScale) {
+ float animationScale, int finalWidth, int finalHeight) {
if (mSurface == null) {
// Can't do animation.
return false;
@@ -248,16 +241,12 @@
break;
}
- mDisplay.getRealMetrics(mDisplayMetrics);
-
// Initialize the animations. This is a hack, redefining what "parent"
// means to allow supplying the last and next size. In this definition
// "%p" is the original (let's call it "previous") size, and "%" is the
// screen's current/new size.
- mEnterAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
- mOriginalWidth, mOriginalHeight);
- mExitAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
- mOriginalWidth, mOriginalHeight);
+ mEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+ mExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
mStarted = false;
mExitAnimation.restrictDuration(maxAnimationDuration);
@@ -270,10 +259,8 @@
Surface.openTransaction();
try {
- final int w = mDisplayMetrics.widthPixels;
- final int h = mDisplayMetrics.heightPixels;
- Rect outer = new Rect(-w, -h, w*2, h*2);
- Rect inner = new Rect(0, 0, w, h);
+ Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2);
+ Rect inner = new Rect(0, 0, finalWidth, finalHeight);
mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 71b5952..768d2db 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -38,9 +38,6 @@
final int mThickness = 20;
public StrictModeFlash(Display display, SurfaceSession session) {
- final DisplayMetrics dm = new DisplayMetrics();
- display.getRealMetrics(dm);
-
try {
mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
} catch (Surface.OutOfResourcesException e) {
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 375abe5..5497eb4 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -50,10 +50,7 @@
int mLastDH;
boolean mDrawNeeded;
- Watermark(Display display, SurfaceSession session, String[] tokens) {
- final DisplayMetrics dm = new DisplayMetrics();
- display.getRealMetrics(dm);
-
+ Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) {
if (false) {
Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
for (int i=0; i<tokens.length; i++) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index be21ac0..f8059f5 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -465,6 +465,7 @@
Display mDisplay;
final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics();
final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics();
final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics();
@@ -5642,15 +5643,14 @@
}
config.orientation = orientation;
- DisplayMetrics dm = mDisplayMetrics;
- mDisplay.getRealMetrics(dm);
+ // Update real display metrics.
+ mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight);
- // Override display width and height with what we are computing,
- // to be sure they remain consistent.
- dm.widthPixels = dm.noncompatWidthPixels = mAppDisplayWidth
- = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
- dm.heightPixels = dm.noncompatHeightPixels = mAppDisplayHeight
- = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+ // Update application display metrics.
+ final DisplayMetrics dm = mDisplayMetrics;
+ mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
+ mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+ mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);
mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
mCompatDisplayMetrics);
@@ -6086,8 +6086,8 @@
}
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
- mInitialDisplayWidth = mDisplay.getRealWidth();
- mInitialDisplayHeight = mDisplay.getRealHeight();
+ mInitialDisplayWidth = mDisplay.getRawWidth();
+ mInitialDisplayHeight = mDisplay.getRawHeight();
int rot = mDisplay.getRotation();
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
// If the screen is currently rotated, we need to swap the
@@ -6098,7 +6098,9 @@
}
mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
- mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight());
+ mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
+ mDisplay.getRawWidth(), mDisplay.getRawHeight(),
+ mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight);
}
@@ -6602,6 +6604,13 @@
}
}
+ public void getRealDisplaySize(Point size) {
+ synchronized(mWindowMap) {
+ size.x = mCurDisplayWidth;
+ size.y = mCurDisplayHeight;
+ }
+ }
+
public int getMaximumSizeDimension() {
synchronized(mWindowMap) {
// Do this based on the raw screen size, until we are smarter.
@@ -8687,7 +8696,8 @@
}
if (mScreenRotationAnimation == null) {
mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
- mDisplay, mFxSession, inTransaction);
+ mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+ mDisplay.getRotation());
}
if (!mScreenRotationAnimation.hasScreenshot()) {
Surface.freezeDisplay(0);
@@ -8717,7 +8727,7 @@
if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
&& mScreenRotationAnimation.hasScreenshot()) {
if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
- mTransitionAnimationScale)) {
+ mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
requestAnimationLocked(0);
} else {
mScreenRotationAnimation = null;
@@ -8797,7 +8807,7 @@
if (line != null) {
String[] toks = line.split("%");
if (toks != null && toks.length > 0) {
- mWatermark = new Watermark(mDisplay, mFxSession, toks);
+ mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks);
}
}
} catch (FileNotFoundException e) {
@@ -9063,8 +9073,6 @@
pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
pw.print(" app=");
pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
- pw.print(" real="); pw.print(mDisplay.getRealWidth());
- pw.print("x"); pw.print(mDisplay.getRealHeight());
pw.print(" raw="); pw.print(mDisplay.getRawWidth());
pw.print("x"); pw.println(mDisplay.getRawHeight());
} else {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index d298ff7..cacb3e7 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -497,8 +497,8 @@
}
if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
- mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getRealWidth(),
- mService.mDisplay.getRealHeight(), false);
+ mService.updateWallpaperOffsetLocked(this,
+ mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
}
if (WindowManagerService.localLOGV) {
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index de9c9d0..3414eea 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -166,7 +166,8 @@
void dump(String8& dump);
- void setDisplaySize(int32_t displayId, int32_t width, int32_t height);
+ void setDisplaySize(int32_t displayId, int32_t width, int32_t height,
+ int32_t externalWidth, int32_t externalHeight);
void setDisplayOrientation(int32_t displayId, int32_t orientation);
status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
@@ -181,7 +182,7 @@
/* --- InputReaderPolicyInterface implementation --- */
- virtual bool getDisplayInfo(int32_t displayId,
+ virtual bool getDisplayInfo(int32_t displayId, bool external,
int32_t* width, int32_t* height, int32_t* orientation);
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
@@ -221,7 +222,8 @@
Mutex mLock;
struct Locked {
// Display size information.
- int32_t displayWidth, displayHeight; // -1 when initialized
+ int32_t displayWidth, displayHeight; // -1 when not initialized
+ int32_t displayExternalWidth, displayExternalHeight; // -1 when not initialized
int32_t displayOrientation;
// System UI visibility.
@@ -269,6 +271,8 @@
AutoMutex _l(mLock);
mLocked.displayWidth = -1;
mLocked.displayHeight = -1;
+ mLocked.displayExternalWidth = -1;
+ mLocked.displayExternalHeight = -1;
mLocked.displayOrientation = ROTATION_0;
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
@@ -305,22 +309,24 @@
return false;
}
-void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
+void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height,
+ int32_t externalWidth, int32_t externalHeight) {
if (displayId == 0) {
{ // acquire lock
AutoMutex _l(mLock);
- if (mLocked.displayWidth == width && mLocked.displayHeight == height) {
- return;
+ if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+ mLocked.displayWidth = width;
+ mLocked.displayHeight = height;
+
+ sp<PointerController> controller = mLocked.pointerController.promote();
+ if (controller != NULL) {
+ controller->setDisplaySize(width, height);
+ }
}
- mLocked.displayWidth = width;
- mLocked.displayHeight = height;
-
- sp<PointerController> controller = mLocked.pointerController.promote();
- if (controller != NULL) {
- controller->setDisplaySize(width, height);
- }
+ mLocked.displayExternalWidth = externalWidth;
+ mLocked.displayExternalHeight = externalHeight;
} // release lock
}
}
@@ -352,7 +358,7 @@
return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
}
-bool NativeInputManager::getDisplayInfo(int32_t displayId,
+bool NativeInputManager::getDisplayInfo(int32_t displayId, bool external,
int32_t* width, int32_t* height, int32_t* orientation) {
bool result = false;
if (displayId == 0) {
@@ -360,10 +366,10 @@
if (mLocked.displayWidth > 0 && mLocked.displayHeight > 0) {
if (width) {
- *width = mLocked.displayWidth;
+ *width = external ? mLocked.displayExternalWidth : mLocked.displayWidth;
}
if (height) {
- *height = mLocked.displayHeight;
+ *height = external ? mLocked.displayExternalHeight : mLocked.displayHeight;
}
if (orientation) {
*orientation = mLocked.displayOrientation;
@@ -952,7 +958,7 @@
}
static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
- jint displayId, jint width, jint height) {
+ jint displayId, jint width, jint height, jint externalWidth, jint externalHeight) {
if (checkInputManagerUnitialized(env)) {
return;
}
@@ -961,7 +967,7 @@
// to be passed in like this, not sure which is better but leaving it like this
// keeps the window manager in direct control of when display transitions propagate down
// to the input dispatcher
- gNativeInputManager->setDisplaySize(displayId, width, height);
+ gNativeInputManager->setDisplaySize(displayId, width, height, externalWidth, externalHeight);
}
static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
@@ -1291,7 +1297,7 @@
(void*) android_server_InputManager_nativeInit },
{ "nativeStart", "()V",
(void*) android_server_InputManager_nativeStart },
- { "nativeSetDisplaySize", "(III)V",
+ { "nativeSetDisplaySize", "(IIIII)V",
(void*) android_server_InputManager_nativeSetDisplaySize },
{ "nativeSetDisplayOrientation", "(II)V",
(void*) android_server_InputManager_nativeSetDisplayOrientation },
diff --git a/services/jni/com_android_server_location_GpsLocationProvider.cpp b/services/jni/com_android_server_location_GpsLocationProvider.cpp
index 87ffcba..c29be3a 100755
--- a/services/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -163,8 +163,15 @@
static void agps_status_callback(AGpsStatus* agps_status)
{
JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ uint32_t ipaddr;
+ // ipaddr field was not included in original AGpsStatus
+ if (agps_status->size >= sizeof(AGpsStatus))
+ ipaddr = agps_status->ipaddr;
+ else
+ ipaddr = 0xFFFFFFFF;
env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus,
- agps_status->type, agps_status->status);
+ agps_status->type, agps_status->status, ipaddr);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
@@ -233,7 +240,7 @@
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
- method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
+ method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(III)V");
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
diff --git a/services/powermanager/Android.mk b/services/powermanager/Android.mk
new file mode 100644
index 0000000..d98b2da
--- /dev/null
+++ b/services/powermanager/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ IPowerManager.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder
+
+LOCAL_MODULE:= libpowermanager
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
new file mode 100644
index 0000000..a0f19d4
--- /dev/null
+++ b/services/powermanager/IPowerManager.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IPowerManager"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <powermanager/IPowerManager.h>
+
+namespace android {
+
+// must be kept in sync with IPowerManager.aidl
+enum {
+ ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
+ RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 4,
+};
+
+class BpPowerManager : public BpInterface<IPowerManager>
+{
+public:
+ BpPowerManager(const sp<IBinder>& impl)
+ : BpInterface<IPowerManager>(impl)
+ {
+ }
+
+ virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+
+ data.writeInt32(flags);
+ data.writeStrongBinder(lock);
+ data.writeString16(tag);
+ // no WorkSource passed
+ data.writeInt32(0);
+ return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply);
+ }
+
+ virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+ data.writeStrongBinder(lock);
+ data.writeInt32(flags);
+ return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index e0268fa..7d6a14d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -352,12 +352,13 @@
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
+ "doTransaction: "
"resize (layer=%p), requested (%dx%d), drawing (%d,%d), "
- "fixedSize=%d",
+ "scalingMode=%d",
this,
int(temp.requested_w), int(temp.requested_h),
int(front.requested_w), int(front.requested_h),
- isFixedSize());
+ mCurrentScalingMode);
if (!isFixedSize()) {
// we're being resized and there is a freeze display request,
@@ -492,6 +493,14 @@
// we now have the correct size, unfreeze the screen
mFreezeLock.clear();
}
+
+ LOGD_IF(DEBUG_RESIZE,
+ "lockPageFlip : "
+ " (layer=%p), buffer (%ux%u, tr=%02x), "
+ "requested (%dx%d)",
+ this,
+ bufWidth, bufHeight, mCurrentTransform,
+ front.requested_w, front.requested_h);
}
}
}
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 24d5f9a..05b7527 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -308,7 +308,7 @@
bool Transform::preserveRects() const
{
- return (type() & ROT_INVALID) ? false : true;
+ return (getOrientation() & ROT_INVALID) ? false : true;
}
void Transform::dump(const char* name) const
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index ee5f3f5..1620405 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -29,6 +29,7 @@
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 1234bfd..46bcc4a 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -29,12 +29,13 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
/**
* This test exercises the
- * {@link com.android.server.AccessibilityManagerService} by mocking the
+ * {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the
* {@link android.view.accessibility.AccessibilityManager} which talks to to the
* service. The service itself is interacting with the platform. Note: Testing
* the service in full isolation would require significant amount of work for
@@ -97,7 +98,9 @@
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+ final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityDisabled =
+ (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertFalse("The client must be disabled since accessibility is disabled.",
@@ -107,7 +110,10 @@
ensureAccessibilityEnabled(mContext, true);
// invoke the method under test
- boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+ final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityEnabled =
+ (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+
// check expected result
assertTrue("The client must be enabled since accessibility is enabled.",
@@ -123,7 +129,9 @@
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+ final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityEnabled =
+ (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertTrue("The client must be enabled since accessibility is enabled.",
@@ -133,7 +141,9 @@
ensureAccessibilityEnabled(mContext, false);
// invoke the method under test
- boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+ final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityDisabled =
+ (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertFalse("The client must be disabled since accessibility is disabled.",
@@ -537,10 +547,10 @@
* This class is a mock {@link IAccessibilityManagerClient}.
*/
public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub {
- boolean mIsEnabled;
+ int mState;
- public void setEnabled(boolean enabled) {
- mIsEnabled = enabled;
+ public void setState(int state) {
+ mState = state;
}
public void setTouchExplorationEnabled(boolean enabled) {
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index 1463d30..e083815 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -70,7 +70,8 @@
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn(
expectedServices);
replay(mockServiceInterface);
@@ -91,7 +92,8 @@
public void testInterrupt() throws Exception {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
mockServiceInterface.interrupt();
replay(mockServiceInterface);
@@ -107,7 +109,8 @@
public void testIsEnabled() throws Exception {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
replay(mockServiceInterface);
// invoke the method under test
@@ -118,7 +121,7 @@
assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled);
// disable accessibility
- manager.getClient().setEnabled(false);
+ manager.getClient().setState(0);
// wait for the asynchronous IBinder call to complete
Thread.sleep(TIMEOUT_BINDER_CALL);
@@ -141,7 +144,8 @@
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
.andReturn(true);
expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
@@ -176,7 +180,7 @@
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(false);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0);
replay(mockServiceInterface);
// invoke the method under test (accessibility disabled)
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 504ba42..aab09ca 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -20,6 +20,7 @@
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.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -27,6 +28,10 @@
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
+import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
import static org.easymock.EasyMock.anyInt;
import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.capture;
@@ -39,12 +44,14 @@
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.IProcessObserver;
+import android.app.Notification;
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.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkStatsService;
import android.net.LinkProperties;
@@ -95,7 +102,7 @@
private IActivityManager mActivityManager;
private IPowerManager mPowerManager;
private INetworkStatsService mStatsService;
- private INetworkManagementService mNetworkManagement;
+ private INetworkManagementService mNetworkManager;
private INetworkPolicyListener mPolicyListener;
private TrustedTime mTime;
private IConnectivityManager mConnManager;
@@ -103,6 +110,7 @@
private NetworkPolicyManagerService mService;
private IProcessObserver mProcessObserver;
+ private INetworkManagementEventObserver mNetworkObserver;
private Binder mStubBinder = new Binder();
@@ -141,6 +149,11 @@
}
};
}
+
+ @Override
+ public void startActivity(Intent intent) {
+ // ignored
+ }
};
mPolicyDir = getContext().getFilesDir();
@@ -151,7 +164,7 @@
mActivityManager = createMock(IActivityManager.class);
mPowerManager = createMock(IPowerManager.class);
mStatsService = createMock(INetworkStatsService.class);
- mNetworkManagement = createMock(INetworkManagementService.class);
+ mNetworkManager = createMock(INetworkManagementService.class);
mPolicyListener = createMock(INetworkPolicyListener.class);
mTime = createMock(TrustedTime.class);
mConnManager = createMock(IConnectivityManager.class);
@@ -159,7 +172,7 @@
mService = new NetworkPolicyManagerService(
mServiceContext, mActivityManager, mPowerManager, mStatsService,
- mNetworkManagement, mTime, mPolicyDir);
+ mNetworkManager, mTime, mPolicyDir);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
@@ -169,11 +182,17 @@
mService.registerListener(mPolicyListener);
verifyAndReset();
- // catch the registered IProcessObserver during systemReady()
+ // catch IProcessObserver during systemReady()
final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
mActivityManager.registerProcessObserver(capture(processObserver));
expectLastCall().atLeastOnce();
+ // catch INetworkManagementEventObserver during systemReady()
+ final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+ INetworkManagementEventObserver>();
+ mNetworkManager.registerObserver(capture(networkObserver));
+ expectLastCall().atLeastOnce();
+
// expect to answer screen status during systemReady()
expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
expectTime(System.currentTimeMillis());
@@ -186,6 +205,7 @@
verifyAndReset();
mProcessObserver = processObserver.getValue();
+ mNetworkObserver = networkObserver.getValue();
}
@@ -382,7 +402,8 @@
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(sTemplateWifi, 5, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(
+ sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -392,7 +413,8 @@
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(sTemplateWifi, 20, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(
+ sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -402,7 +424,8 @@
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(sTemplateWifi, 30, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(
+ sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -412,7 +435,8 @@
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(sTemplateWifi, 30, 1024L, 1024L);
+ final NetworkPolicy policy = new NetworkPolicy(
+ sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertEquals(expectedCycle, actualCycle);
}
@@ -432,6 +456,7 @@
state = new NetworkState[] { buildWifi() };
expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectTime(TIME_MAR_10 + elapsedRealtime);
+ expectClearNotifications();
future = expectMeteredIfacesChanged();
replay();
@@ -453,12 +478,14 @@
// TODO: consider making strongly ordered mock
expectRemoveInterfaceQuota(TEST_IFACE);
expectSetInterfaceQuota(TEST_IFACE, 1536L);
+ expectRemoveInterfaceAlert(TEST_IFACE);
+ expectSetInterfaceAlert(TEST_IFACE, 512L);
expectClearNotifications();
future = expectMeteredIfacesChanged(TEST_IFACE);
replay();
- setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L));
+ setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
future.get();
verifyAndReset();
}
@@ -485,6 +512,131 @@
verifyAndReset();
}
+ public void testOverWarningLimitNotification() throws Exception {
+ long elapsedRealtime = 0;
+ long currentTime = 0;
+ NetworkState[] state = null;
+ NetworkStats stats = null;
+ Future<Void> future;
+ Capture<String> tag;
+
+ final long TIME_FEB_15 = 1171497600000L;
+ final long TIME_MAR_10 = 1173484800000L;
+ final int CYCLE_DAY = 15;
+
+ // assign wifi policy
+ elapsedRealtime = 0;
+ currentTime = TIME_MAR_10 + elapsedRealtime;
+ state = new NetworkState[] {};
+
+ {
+ expectTime(currentTime);
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+
+ expectClearNotifications();
+ future = expectMeteredIfacesChanged();
+
+ replay();
+ setNetworkPolicies(
+ new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1024L, 2048L, SNOOZE_NEVER));
+ future.get();
+ verifyAndReset();
+ }
+
+ // bring up wifi network
+ elapsedRealtime += MINUTE_IN_MILLIS;
+ currentTime = TIME_MAR_10 + elapsedRealtime;
+ stats = new NetworkStats(elapsedRealtime, 1)
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L);
+ state = new NetworkState[] { buildWifi() };
+
+ {
+ expectTime(currentTime);
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+ .andReturn(stats).atLeastOnce();
+
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, 2048L);
+ expectRemoveInterfaceAlert(TEST_IFACE);
+ expectSetInterfaceAlert(TEST_IFACE, 1024L);
+
+ expectClearNotifications();
+ future = expectMeteredIfacesChanged(TEST_IFACE);
+
+ replay();
+ mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
+ future.get();
+ verifyAndReset();
+ }
+
+ // go over warning, which should kick notification
+ elapsedRealtime += MINUTE_IN_MILLIS;
+ currentTime = TIME_MAR_10 + elapsedRealtime;
+ stats = new NetworkStats(elapsedRealtime, 1)
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L);
+
+ {
+ expectTime(currentTime);
+ expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+ .andReturn(stats).atLeastOnce();
+
+ expectForceUpdate();
+ expectClearNotifications();
+ tag = expectEnqueueNotification();
+
+ replay();
+ mNetworkObserver.limitReached(null, TEST_IFACE);
+ assertNotificationType(TYPE_WARNING, tag.getValue());
+ verifyAndReset();
+ }
+
+ // go over limit, which should kick notification and dialog
+ elapsedRealtime += MINUTE_IN_MILLIS;
+ currentTime = TIME_MAR_10 + elapsedRealtime;
+ stats = new NetworkStats(elapsedRealtime, 1)
+ .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L);
+
+ {
+ expectTime(currentTime);
+ expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+ .andReturn(stats).atLeastOnce();
+
+ expectForceUpdate();
+ expectClearNotifications();
+ tag = expectEnqueueNotification();
+
+ replay();
+ mNetworkObserver.limitReached(null, TEST_IFACE);
+ assertNotificationType(TYPE_LIMIT, tag.getValue());
+ verifyAndReset();
+ }
+
+ // now snooze policy, which should remove quota
+ elapsedRealtime += MINUTE_IN_MILLIS;
+ currentTime = TIME_MAR_10 + elapsedRealtime;
+
+ {
+ expectTime(currentTime);
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTime))
+ .andReturn(stats).atLeastOnce();
+
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectRemoveInterfaceAlert(TEST_IFACE);
+
+ expectClearNotifications();
+ tag = expectEnqueueNotification();
+ future = expectMeteredIfacesChanged();
+
+ replay();
+ mService.snoozePolicy(sTemplateWifi);
+ future.get();
+ assertNotificationType(TYPE_LIMIT_SNOOZED, tag.getValue());
+ verifyAndReset();
+ }
+ }
+
private static long parseTime(String time) {
final Time result = new Time();
result.parse3339(time);
@@ -511,24 +663,46 @@
expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
}
+ private void expectForceUpdate() throws Exception {
+ mStatsService.forceUpdate();
+ expectLastCall().atLeastOnce();
+ }
+
private void expectClearNotifications() throws Exception {
mNotifManager.cancelNotificationWithTag(isA(String.class), isA(String.class), anyInt());
expectLastCall().anyTimes();
}
- private void expectSetInterfaceQuota(String iface, long quota) throws Exception {
- mNetworkManagement.setInterfaceQuota(iface, quota);
+ private Capture<String> expectEnqueueNotification() throws Exception {
+ final Capture<String> tag = new Capture<String>();
+ mNotifManager.enqueueNotificationWithTag(isA(String.class), capture(tag), anyInt(),
+ isA(Notification.class), isA(int[].class));
+ return tag;
+ }
+
+ private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+ mNetworkManager.setInterfaceQuota(iface, quotaBytes);
expectLastCall().atLeastOnce();
}
private void expectRemoveInterfaceQuota(String iface) throws Exception {
- mNetworkManagement.removeInterfaceQuota(iface);
+ mNetworkManager.removeInterfaceQuota(iface);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
+ mNetworkManager.setInterfaceAlert(iface, alertBytes);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectRemoveInterfaceAlert(String iface) throws Exception {
+ mNetworkManager.removeInterfaceAlert(iface);
expectLastCall().atLeastOnce();
}
private void expectSetUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces)
throws Exception {
- mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
+ mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
expectLastCall().atLeastOnce();
}
@@ -563,15 +737,20 @@
}
}
+ private static void assertNotificationType(int expected, String actualTag) {
+ assertEquals(
+ Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
+ }
+
private void replay() {
EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManagement, mTime, mConnManager, mNotifManager);
+ mNetworkManager, mTime, mConnManager, mNotifManager);
}
private void verifyAndReset() {
EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManagement, mTime, mConnManager, mNotifManager);
+ mNetworkManager, mTime, mConnManager, mNotifManager);
EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener,
- mNetworkManagement, mTime, mConnManager, mNotifManager);
+ mNetworkManager, mTime, mConnManager, mNotifManager);
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index a69ce8b..6d8956f 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -142,13 +142,15 @@
} catch (IllegalArgumentException e) {
throw new UnknownHostException("Non-numeric ip addr=" + addr);
}
- if (addrPrefixLen == 0) {
- // Assume point to point
- addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+ if (! ia.isAnyLocalAddress()) {
+ if (addrPrefixLen == 0) {
+ // Assume point to point
+ addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+ }
+ if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
+ la = new LinkAddress(ia, addrPrefixLen);
+ linkProperties.addLinkAddress(la);
}
- if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
- la = new LinkAddress(ia, addrPrefixLen);
- linkProperties.addLinkAddress(la);
}
} else {
throw new UnknownHostException("no address for ifname=" + ifname);
@@ -163,21 +165,24 @@
} catch (IllegalArgumentException e) {
throw new UnknownHostException("Non-numeric dns addr=" + addr);
}
- linkProperties.addDns(ia);
+ if (! ia.isAnyLocalAddress()) {
+ linkProperties.addDns(ia);
+ }
}
} else if (okToUseSystemPropertyDns){
String dnsServers[] = new String[2];
dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
for (String dnsAddr : dnsServers) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(dnsAddr);
- } catch (IllegalArgumentException e) {
- throw new UnknownHostException("Non-numeric dns addr="
- + dnsAddr);
- }
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(dnsAddr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric dns addr=" + dnsAddr);
+ }
+ if (! ia.isAnyLocalAddress()) {
linkProperties.addDns(ia);
+ }
}
} else {
throw new UnknownHostException("Empty dns response and no system default dns");
@@ -199,7 +204,9 @@
} catch (IllegalArgumentException e) {
throw new UnknownHostException("Non-numeric gateway addr=" + addr);
}
- linkProperties.addRoute(new RouteInfo(ia));
+ if (! ia.isAnyLocalAddress()) {
+ linkProperties.addRoute(new RouteInfo(ia));
+ }
}
result = SetupResult.SUCCESS;
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 8978f1d..636646e 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -447,6 +447,7 @@
lastFailCause = FailCause.NONE;
mRetryOverride = -1;
mRefCount = 0;
+ cid = -1;
mLinkProperties = new LinkProperties();
mApn = null;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index d3bb6a5..4d86903 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -217,6 +217,26 @@
" mNewDataConnectionState = " + mNewDataConnectionState);
}
+ // TODO: Add proper support for LTE Only, we should be looking at
+ // the preferred network mode, to know when newSS state should
+ // be coming from mLteSs state. This was needed to pass a VZW
+ // LTE Only test.
+ //
+ // If CDMA service is OOS, double check if the device is running with LTE only
+ // mode. If that is the case, derive the service state from LTE side.
+ // To set in LTE only mode, sqlite3 /data/data/com.android.providers.settings/
+ // databases/settings.db "update secure set value='11' where name='preferred_network_mode'"
+ if (newSS.getState() == ServiceState.STATE_OUT_OF_SERVICE) {
+ int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
+ .getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ RILConstants.PREFERRED_NETWORK_MODE);
+ if (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY) {
+ if (DBG) log("pollState: LTE Only mode");
+ newSS.setState(mLteSS.getState());
+ }
+ }
+
if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index 3c2db54..2eca384 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -27,8 +27,8 @@
>
<TextView
- android:text="Email account"
- android:textSize="48dip"
+ android:text="Email setup"
+ android:textSize="32dip"
android:layout_columnSpan="4"
android:layout_gravity="center_horizontal"
@@ -36,7 +36,7 @@
<TextView
android:text="You can configure email in just a few steps:"
- android:textSize="20dip"
+ android:textSize="16dip"
android:layout_columnSpan="4"
android:layout_gravity="left"
@@ -49,7 +49,7 @@
/>
<EditText
- android:layout_width="100dip"
+ android:layout_width="64dip"
/>
<TextView
@@ -60,14 +60,14 @@
/>
<EditText
- android:layout_width="50dip"
+ android:layout_width="32dip"
/>
<Space
android:layout_row="4"
android:layout_column="2"
- android:layout_rowFlexibility="canStretch"
- android:layout_columnFlexibility="canStretch"
+ android:layout_margin="0dip"
+ android:layout_gravity="fill"
/>
<Button
@@ -75,7 +75,6 @@
android:layout_row="5"
android:layout_column="3"
- android:layout_gravity="fill_horizontal"
/>
<Button
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index 38a85a3..e1871ac 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -38,30 +38,31 @@
vg.setUseDefaultMargins(true);
vg.setAlignmentMode(ALIGN_BOUNDS);
- Spec row1 = spec(0, CENTER);
- Spec row2 = spec(1, CENTER);
+ Spec row1 = spec(0);
+ Spec row2 = spec(1);
Spec row3 = spec(2, BASELINE);
Spec row4 = spec(3, BASELINE);
- Spec row5 = spec(4, FILL, CAN_STRETCH);
- Spec row6 = spec(5, CENTER);
- Spec row7 = spec(6, CENTER);
+ Spec row5 = spec(4, FILL);
+ Spec row6 = spec(5);
+ Spec row7 = spec(6);
Spec col1a = spec(0, 4, CENTER);
Spec col1b = spec(0, 4, LEFT);
Spec col1c = spec(0, RIGHT);
Spec col2 = spec(1, LEFT);
- Spec col3 = spec(2, FILL, CAN_STRETCH);
- Spec col4 = spec(3, FILL);
+ Spec col3 = spec(2, FILL);
+ Spec col4a = spec(3);
+ Spec col4b = spec(3, FILL);
{
TextView v = new TextView(context);
- v.setTextSize(48);
+ v.setTextSize(32);
v.setText("Email setup");
vg.addView(v, new LayoutParams(row1, col1a));
}
{
TextView v = new TextView(context);
- v.setTextSize(20);
+ v.setTextSize(16);
v.setText("You can configure email in just a few steps:");
vg.addView(v, new LayoutParams(row2, col1b));
}
@@ -75,7 +76,7 @@
v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
{
LayoutParams lp = new LayoutParams(row3, col2);
- lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone@bedrock.com ");
+ lp.width = (int) v.getPaint().measureText("Frederick.W.Flintstone");
vg.addView(v, lp);
}
}
@@ -95,17 +96,19 @@
}
{
Space v = new Space(context);
- vg.addView(v, new LayoutParams(row5, col3));
+ LayoutParams lp = new LayoutParams(row5, col3);
+ lp.setMargins(0, 0, 0, 0);
+ vg.addView(v, lp);
}
{
Button v = new Button(context);
v.setText("Manual setup");
- vg.addView(v, new LayoutParams(row6, col4));
+ vg.addView(v, new LayoutParams(row6, col4a));
}
{
Button v = new Button(context);
v.setText("Next");
- vg.addView(v, new LayoutParams(row7, col4));
+ vg.addView(v, new LayoutParams(row7, col4b));
}
return vg;
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9fcd05a..d74d80d 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,15 @@
android:hardwareAccelerated="true">
<activity
+ android:name="TextFadeActivity"
+ android:label="_TextFade">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="MaxBitmapSizeActivity"
android:label="_MaxBitmapSize">
<intent-filter>
diff --git a/tests/HwAccelerationTest/res/layout/text_fade.xml b/tests/HwAccelerationTest/res/layout/text_fade.xml
new file mode 100644
index 0000000..8da2204
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/text_fade.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/contact_tile_name"
+ android:layout_width="105dip"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="8dip"
+ android:layout_marginBottom="20dip"
+ android:textColor="@android:color/white"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdgeLength="16sp"
+ android:fadingEdge="horizontal"
+ android:text="This is a really really really really really really long string"
+ android:textSize="16sp" />
+
+</FrameLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java
new file mode 100644
index 0000000..c8bbc7d
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextFadeActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class TextFadeActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.text_fade);
+ }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
index 16ebe08..d93238c 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.rs
@@ -84,10 +84,10 @@
fs.radius = radius;
fs.ain = rsGetAllocation(ScratchPixel1);
- rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs);
+ rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
fs.ain = rsGetAllocation(ScratchPixel2);
- rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs);
+ rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
rsSendToClientBlocking(CMD_FINISHED);
}
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
index f046952..5c5b1c9 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/scenegraph.rs
@@ -60,7 +60,7 @@
robot2Ptr->transforms[1].w += 2.5f;
robot2Ptr->isDirty = 1;
- rsForEach(gTransformRS, gRootNode->children, gRootNode->children, 0);
+ rsForEach(gTransformRS, gRootNode->children, gRootNode->children);
rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
rsgClearDepth(1.0f);
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
index f328025..85c0630 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/transform.rs
@@ -91,6 +91,6 @@
//rsDebug("Transform calling self with child ", (int)data->children.p);
if (data->children.p) {
- rsForEach(transformScript, data->children, data->children, (void*)&toChild);
+ rsForEach(transformScript, data->children, data->children, (void*)&toChild, sizeof(toChild));
}
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index eaafe1d..db97835 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -280,7 +280,7 @@
testData.renderSurfaceW = gRenderSurfaceW;
testData.renderSurfaceH = gRenderSurfaceH;
testData.user = fillNum;
- rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData);
+ rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
}
static void bindProgramVertexOrtho() {
@@ -520,7 +520,7 @@
testData.user = 0;
testData.user1 = useTexture ? 1 : 0;
testData.user2 = numMeshes;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+ rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
}
static void displayCustomShaderSamples(int numMeshes) {
@@ -530,7 +530,7 @@
testData.dt = gDt;
testData.user = 1;
testData.user1 = numMeshes;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+ rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
}
static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
@@ -541,7 +541,7 @@
testData.user = 2;
testData.user1 = numMeshes;
testData.user2 = heavyVertex ? 1 : 0;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData);
+ rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
}
static void displayMultitextureSample(bool blend, int quadCount) {
diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp
index 580528d..18775c0 100644
--- a/tools/aapt/FileFinder.cpp
+++ b/tools/aapt/FileFinder.cpp
@@ -9,7 +9,6 @@
#include <utils/String8.h>
#include <utils/KeyedVector.h>
-#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
@@ -19,8 +18,6 @@
//#define DEBUG
using android::String8;
-using std::cout;
-using std::endl;
// Private function to check whether a file is a directory or not
bool isDirectory(const char* filename) {
@@ -50,9 +47,6 @@
if (!dw->openDir(basePath)) {
return false;
}
-#ifdef DEBUG
- cout << "FileFinder looking in " << basePath << endl;
-#endif // DEBUG
/*
* Go through all directory entries. Check each file using checkAndAddFile
* and recurse into sub-directories.
@@ -87,9 +81,6 @@
Vector<String8>& extensions,
KeyedVector<String8,time_t>& fileStore)
{
-#ifdef DEBUG
- cout << "Checking file " << path << "...";
-#endif // DEBUG
// Loop over the extensions, checking for a match
bool done = false;
String8 ext(path.getPathExtension());
@@ -99,15 +90,9 @@
ext2.toLower();
// Compare the extensions. If a match is found, add to storage.
if (ext == ext2) {
-#ifdef DEBUG
- cout << "Match";
-#endif // DEBUG
done = true;
fileStore.add(path,stats->st_mtime);
}
}
-#ifdef DEBUG
- cout << endl;
-#endif //DEBUG
}
diff --git a/tools/aapt/ZipFile.h b/tools/aapt/ZipFile.h
index dbbd072..7877550 100644
--- a/tools/aapt/ZipFile.h
+++ b/tools/aapt/ZipFile.h
@@ -57,7 +57,7 @@
/*
* Open a new or existing archive.
*/
- typedef enum {
+ enum {
kOpenReadOnly = 0x01,
kOpenReadWrite = 0x02,
kOpenCreate = 0x04, // create if it doesn't exist
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 13cd9ec..d94f369 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -76,6 +76,9 @@
public void getDisplaySize(Point arg0) throws RemoteException {
}
+ public void getRealDisplaySize(Point arg0) throws RemoteException {
+ }
+
// ---- unused implementation of IWindowManager ----
public boolean canStatusBarHide() throws RemoteException {
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 49ddf1d..0e24cc0 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
@@ -117,8 +117,10 @@
int accessDelegate = access;
// change access to public for the original one
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
+ if (Main.sOptions.generatePublicAccess) {
+ access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+ access |= Opcodes.ACC_PUBLIC;
+ }
MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
desc, signature, exceptions);
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index ce48069..9bf52c7 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -37,7 +37,7 @@
* which does:
* <pre>
* $ make layoutlib_create <bunch of framework jars>
- * $ out/host/linux-x86/framework/bin/layoutlib_create \
+ * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \
* out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \
* out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \
* out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
@@ -45,6 +45,12 @@
*/
public class Main {
+ public static class Options {
+ public boolean generatePublicAccess = true;
+ }
+
+ public static final Options sOptions = new Options();
+
public static void main(String[] args) {
Log log = new Log();
@@ -53,7 +59,7 @@
String[] osDestJar = { null };
if (!processArgs(log, args, osJarPath, osDestJar)) {
- log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
+ log.error("Usage: layoutlib_create [-v] [-p] output.jar input.jar ...");
System.exit(1);
}
@@ -136,6 +142,8 @@
String s = args[i];
if (s.equals("-v")) {
log.setVerbose(true);
+ } else if (s.equals("-p")) {
+ sOptions.generatePublicAccess = false;
} else if (!s.startsWith("-")) {
if (osDestJar[0] == null) {
osDestJar[0] = s;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
index f2d9755..5a0a44a4 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
@@ -72,8 +72,10 @@
name = mClassName;
// remove protected or private and set as public
- access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
- access |= Opcodes.ACC_PUBLIC;
+ if (Main.sOptions.generatePublicAccess) {
+ access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+ access |= Opcodes.ACC_PUBLIC;
+ }
// remove final
access = access & ~Opcodes.ACC_FINAL;
// note: leave abstract classes as such
@@ -87,8 +89,10 @@
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
// remove protected or private and set as public
- access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
- access |= Opcodes.ACC_PUBLIC;
+ if (Main.sOptions.generatePublicAccess) {
+ access = access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
+ access |= Opcodes.ACC_PUBLIC;
+ }
// remove final
access = access & ~Opcodes.ACC_FINAL;
// note: leave abstract classes as such
@@ -117,8 +121,10 @@
String methodSignature = mClassName.replace('/', '.') + "#" + name;
// change access to public
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
+ if (Main.sOptions.generatePublicAccess) {
+ access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+ access |= Opcodes.ACC_PUBLIC;
+ }
// remove final
access = access & ~Opcodes.ACC_FINAL;
@@ -155,9 +161,10 @@
public FieldVisitor visitField(int access, String name, String desc, String signature,
Object value) {
// change access to public
- access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
- access |= Opcodes.ACC_PUBLIC;
-
+ if (Main.sOptions.generatePublicAccess) {
+ access &= ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE);
+ access |= Opcodes.ACC_PUBLIC;
+ }
return super.visitField(access, name, desc, signature, value);
}
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index 47ed658..0815294 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -49,7 +49,8 @@
frameworks/base/media/libstagefright/codecs/amrnb/enc/include \
frameworks/base/media/libstagefright/codecs/amrnb/enc/src \
frameworks/base/media/libstagefright/codecs/amrnb/dec/include \
- frameworks/base/media/libstagefright/codecs/amrnb/dec/src
+ frameworks/base/media/libstagefright/codecs/amrnb/dec/src \
+ system/media/audio_effects/include
LOCAL_CFLAGS += -fvisibility=hidden
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 85ed1c8..529b425 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -40,7 +40,8 @@
#include <media/AudioRecord.h>
#include <media/AudioTrack.h>
#include <media/mediarecorder.h>
-
+#include <media/AudioEffect.h>
+#include <audio_effects/effect_aec.h>
#include <system/audio.h>
#include "jni.h"
@@ -481,6 +482,7 @@
bool sendDtmf(int event);
bool add(AudioStream *stream);
bool remove(int socket);
+ bool platformHasAec() { return mPlatformHasAec; }
private:
enum {
@@ -491,6 +493,8 @@
LAST_MODE = 3,
};
+ bool checkPlatformAec();
+
AudioStream *mChain;
int mEventQueue;
volatile int mDtmfEvent;
@@ -499,6 +503,7 @@
int mSampleRate;
int mSampleCount;
int mDeviceSocket;
+ bool mPlatformHasAec;
class NetworkThread : public Thread
{
@@ -550,6 +555,7 @@
mDeviceSocket = -1;
mNetworkThread = new NetworkThread(this);
mDeviceThread = new DeviceThread(this);
+ mPlatformHasAec = checkPlatformAec();
}
AudioGroup::~AudioGroup()
@@ -630,10 +636,6 @@
if (mode == NORMAL && !strcmp(value, "herring")) {
mode = ECHO_SUPPRESSION;
}
- if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters(
- 0, String8("ec_supported")) == "ec_supported=yes") {
- mode = NORMAL;
- }
if (mMode == mode) {
return true;
}
@@ -759,6 +761,25 @@
return true;
}
+bool AudioGroup::checkPlatformAec()
+{
+ effect_descriptor_t fxDesc;
+ uint32_t numFx;
+
+ if (AudioEffect::queryNumberEffects(&numFx) != NO_ERROR) {
+ return false;
+ }
+ for (uint32_t i = 0; i < numFx; i++) {
+ if (AudioEffect::queryEffect(i, &fxDesc) != NO_ERROR) {
+ continue;
+ }
+ if (memcmp(&fxDesc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool AudioGroup::DeviceThread::threadLoop()
{
int mode = mGroup->mMode;
@@ -798,10 +819,6 @@
}
LOGD("latency: output %d, input %d", track.latency(), record.latency());
- // Initialize echo canceler.
- EchoSuppressor echo(sampleCount,
- (track.latency() + record.latency()) * sampleRate / 1000);
-
// Give device socket a reasonable buffer size.
setsockopt(deviceSocket, SOL_SOCKET, SO_RCVBUF, &output, sizeof(output));
setsockopt(deviceSocket, SOL_SOCKET, SO_SNDBUF, &output, sizeof(output));
@@ -810,6 +827,33 @@
char c;
while (recv(deviceSocket, &c, 1, MSG_DONTWAIT) == 1);
+ // check if platform supports echo cancellation and do not active local echo suppression in
+ // this case
+ EchoSuppressor *echo = NULL;
+ AudioEffect *aec = NULL;
+ if (mode == ECHO_SUPPRESSION) {
+ if (mGroup->platformHasAec()) {
+ aec = new AudioEffect(FX_IID_AEC,
+ NULL,
+ 0,
+ 0,
+ 0,
+ record.getSessionId(),
+ record.getInput());
+ status_t status = aec->initCheck();
+ if (status == NO_ERROR || status == ALREADY_EXISTS) {
+ aec->setEnabled(true);
+ } else {
+ delete aec;
+ aec = NULL;
+ }
+ }
+ // Create local echo suppressor if platform AEC cannot be used.
+ if (aec == NULL) {
+ echo = new EchoSuppressor(sampleCount,
+ (track.latency() + record.latency()) * sampleRate / 1000);
+ }
+ }
// Start AudioRecord before AudioTrack. This prevents AudioTrack from being
// disabled due to buffer underrun while waiting for AudioRecord.
if (mode != MUTED) {
@@ -843,7 +887,7 @@
track.releaseBuffer(&buffer);
} else if (status != TIMED_OUT && status != WOULD_BLOCK) {
LOGE("cannot write to AudioTrack");
- return true;
+ goto exit;
}
}
@@ -859,7 +903,7 @@
record.releaseBuffer(&buffer);
} else if (status != TIMED_OUT && status != WOULD_BLOCK) {
LOGE("cannot read from AudioRecord");
- return true;
+ goto exit;
}
}
}
@@ -870,15 +914,18 @@
}
if (mode != MUTED) {
- if (mode == NORMAL) {
- send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
- } else {
- echo.run(output, input);
- send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
+ if (echo != NULL) {
+ LOGV("echo->run()");
+ echo->run(output, input);
}
+ send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
}
}
- return false;
+
+exit:
+ delete echo;
+ delete aec;
+ return true;
}
//------------------------------------------------------------------------------
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 74c6b49..de49eb4 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -217,16 +217,20 @@
/* Start the soft access point */
static final int CMD_START_AP = BASE + 21;
+ /* Indicates soft ap start succeded */
+ static final int CMD_START_AP_SUCCESS = BASE + 22;
+ /* Indicates soft ap start failed */
+ static final int CMD_START_AP_FAILURE = BASE + 23;
/* Stop the soft access point */
- static final int CMD_STOP_AP = BASE + 22;
+ static final int CMD_STOP_AP = BASE + 24;
/* Set the soft access point configuration */
- static final int CMD_SET_AP_CONFIG = BASE + 23;
+ static final int CMD_SET_AP_CONFIG = BASE + 25;
/* Get the soft access point configuration */
- static final int CMD_GET_AP_CONFIG = BASE + 24;
+ static final int CMD_GET_AP_CONFIG = BASE + 26;
/* Set configuration on tether interface */
- static final int CMD_TETHER_INTERFACE = BASE + 25;
+ static final int CMD_TETHER_INTERFACE = BASE + 27;
- static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 26;
+ static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 28;
/* Supplicant commands */
/* Is supplicant alive ? */
@@ -376,10 +380,6 @@
private static final int MIN_RSSI = -200;
private static final int MAX_RSSI = 256;
- /* Constants to indicate if soft ap is running or stopped */
- private static final int SOFT_AP_STOPPED = 0;
- private static final int SOFT_AP_RUNNING = 1;
-
/* Default parent state */
private State mDefaultState = new DefaultState();
/* Temporary initial state */
@@ -423,6 +423,8 @@
/* Waiting for WPS to be completed*/
private State mWaitForWpsCompletionState = new WaitForWpsCompletionState();
+ /* Soft ap is starting up */
+ private State mSoftApStartingState = new SoftApStartingState();
/* Soft ap is running */
private State mSoftApStartedState = new SoftApStartedState();
/* Soft ap is running and we are tethered through connectivity service */
@@ -561,6 +563,7 @@
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
+ addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheredState, mSoftApStartedState);
addState(mWaitForP2pDisableState, mDefaultState);
@@ -1639,28 +1642,27 @@
WifiNative.reconnectCommand();
}
- private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) {
+ /* Current design is to not set the config on a running hostapd but instead
+ * stop and start tethering when user changes config on a running access point
+ *
+ * TODO: Add control channel setup through hostapd that allows changing config
+ * on a running daemon
+ */
+ private boolean startSoftApWithConfig(WifiConfiguration config) {
if (config == null) {
config = WifiApConfigStore.getApConfiguration();
} else {
WifiApConfigStore.setApConfiguration(config);
}
try {
- if (currentStatus == SOFT_AP_STOPPED) {
- nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- } else if (currentStatus == SOFT_AP_RUNNING) {
- //nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- //TODO: when we have a control channel to hostapd, we should not need to do this
- nwService.stopAccessPoint(mInterfaceName);
- nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- }
+ nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
} catch (Exception e) {
Log.e(TAG, "Exception in softap start " + e);
try {
nwService.stopAccessPoint(mInterfaceName);
nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- } catch (Exception ee) {
- Log.e(TAG, "Exception during softap restart : " + ee);
+ } catch (Exception e1) {
+ Log.e(TAG, "Exception in softap re-start " + e1);
return false;
}
}
@@ -1722,6 +1724,8 @@
case CMD_START_DRIVER:
case CMD_STOP_DRIVER:
case CMD_START_AP:
+ case CMD_START_AP_SUCCESS:
+ case CMD_START_AP_FAILURE:
case CMD_STOP_AP:
case CMD_TETHER_INTERFACE:
case CMD_START_SCAN:
@@ -1903,14 +1907,7 @@
}
break;
case CMD_START_AP:
- if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_STOPPED)) {
- Log.d(TAG, "Soft AP start successful");
- setWifiApState(WIFI_AP_STATE_ENABLED);
- transitionTo(mSoftApStartedState);
- } else {
- Log.d(TAG, "Soft AP start failed");
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
- }
+ transitionTo(mSoftApStartingState);
break;
default:
return NOT_HANDLED;
@@ -3061,6 +3058,67 @@
}
}
+ class SoftApStartingState extends State {
+ @Override
+ public void enter() {
+ if (DBG) Log.d(TAG, getName() + "\n");
+ EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
+
+ final Message message = Message.obtain(getCurrentMessage());
+ final WifiConfiguration config = (WifiConfiguration) message.obj;
+
+ // start hostapd on a seperate thread
+ new Thread(new Runnable() {
+ public void run() {
+ if (startSoftApWithConfig(config)) {
+ Log.d(TAG, "Soft AP start successful");
+ sendMessage(CMD_START_AP_SUCCESS);
+ } else {
+ Log.d(TAG, "Soft AP start failed");
+ sendMessage(CMD_START_AP_FAILURE);
+ }
+ }
+ }).start();
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+ switch(message.what) {
+ case CMD_LOAD_DRIVER:
+ case CMD_UNLOAD_DRIVER:
+ case CMD_START_SUPPLICANT:
+ case CMD_STOP_SUPPLICANT:
+ case CMD_START_AP:
+ case CMD_STOP_AP:
+ case CMD_START_DRIVER:
+ case CMD_STOP_DRIVER:
+ case CMD_SET_SCAN_MODE:
+ case CMD_SET_SCAN_TYPE:
+ case CMD_SET_HIGH_PERF_MODE:
+ case CMD_SET_COUNTRY_CODE:
+ case CMD_SET_FREQUENCY_BAND:
+ case CMD_START_PACKET_FILTERING:
+ case CMD_STOP_PACKET_FILTERING:
+ case CMD_TETHER_INTERFACE:
+ case WifiP2pService.P2P_ENABLE_PENDING:
+ deferMessage(message);
+ break;
+ case CMD_START_AP_SUCCESS:
+ setWifiApState(WIFI_AP_STATE_ENABLED);
+ transitionTo(mSoftApStartedState);
+ break;
+ case CMD_START_AP_FAILURE:
+ // initiate driver unload
+ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+ return HANDLED;
+ }
+ }
+
class SoftApStartedState extends State {
@Override
public void enter() {
@@ -3083,17 +3141,9 @@
transitionTo(mDriverLoadedState);
break;
case CMD_START_AP:
- Log.d(TAG,"SoftAP set on a running access point");
- if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_RUNNING)) {
- Log.d(TAG, "Soft AP start successful");
- setWifiApState(WIFI_AP_STATE_ENABLED);
- transitionTo(mSoftApStartedState);
- } else {
- Log.d(TAG, "Soft AP start failed");
- sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0));
- }
+ // Ignore a start on a running access point
break;
- /* Fail client mode operation when soft AP is enabled */
+ /* Fail client mode operation when soft AP is enabled */
case CMD_START_SUPPLICANT:
Log.e(TAG,"Cannot start supplicant with a running soft AP");
setWifiState(WIFI_STATE_UNKNOWN);
diff --git a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
index fa7cf21..be9dfcf 100644
--- a/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiWatchdogStateMachine.java
@@ -32,6 +32,7 @@
import android.net.Uri;
import android.os.Message;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.util.Slog;
@@ -40,16 +41,12 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import java.io.BufferedInputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
-import java.util.Scanner;
-import java.util.regex.Pattern;
/**
* {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi
@@ -87,13 +84,14 @@
private static final int DEFAULT_MIN_DNS_RESPONSES = 3;
private static final long DNS_PING_INTERVAL_MS = 100;
- private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 1500;
+ private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 2000;
private static final long DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000;
- private static final String DEFAULT_WALLED_GARDEN_URL = "http://www.google.com/";
- private static final String DEFAULT_WALLED_GARDEN_PATTERN = "<title>.*Google.*</title>";
-
+ // See http://go/clientsdns for usage approval
+ private static final String DEFAULT_WALLED_GARDEN_URL =
+ "http://clients3.google.com/generate_204";
+ private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;
private static final int BASE = Protocol.BASE_WIFI_WATCHDOG;
@@ -153,7 +151,6 @@
private long mBlacklistFollowupIntervalMs;
private boolean mWalledGardenTestEnabled;
private String mWalledGardenUrl;
- private Pattern mWalledGardenPattern;
private boolean mShowDisabledNotification;
/**
@@ -175,6 +172,7 @@
* It triggers a disableNetwork call if a DNS check fails.
*/
public boolean mDisableAPNextFailure = false;
+ public ConnectivityManager mConnectivityManager;
/**
* STATE MAP
@@ -217,6 +215,12 @@
}
public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
+ ContentResolver contentResolver = context.getContentResolver();
+ // Disable for wifi only devices.
+ if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null &&
+ "wifi-only".equals(SystemProperties.get("ro.carrier"))) {
+ putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false);
+ }
WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
wwsm.start();
wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED);
@@ -312,9 +316,6 @@
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
false, contentObserver);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN),
- false, contentObserver);
}
/**
@@ -323,29 +324,26 @@
* fetches the data we expect
*/
private boolean isWalledGardenConnection() {
- InputStream in = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(mWalledGardenUrl);
urlConnection = (HttpURLConnection) url.openConnection();
- in = new BufferedInputStream(urlConnection.getInputStream());
- Scanner scanner = new Scanner(in);
- if (scanner.findInLine(mWalledGardenPattern) != null) {
- return false;
- } else {
- return true;
- }
+ urlConnection.setInstanceFollowRedirects(false);
+ urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
+ urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
+ urlConnection.setUseCaches(false);
+ urlConnection.getInputStream();
+ // We got a valid response, but not from the real google
+ return urlConnection.getResponseCode() != 204;
} catch (IOException e) {
+ if (DBG) {
+ Slog.d(WWSM_TAG, "Walled garden check - probably not a portal: exception ", e);
+ }
return false;
} finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- }
- }
- if (urlConnection != null)
+ if (urlConnection != null) {
urlConnection.disconnect();
+ }
}
}
@@ -393,9 +391,6 @@
mWalledGardenUrl = getSettingsStr(mContentResolver,
Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL,
DEFAULT_WALLED_GARDEN_URL);
- mWalledGardenPattern = Pattern.compile(getSettingsStr(mContentResolver,
- Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN,
- DEFAULT_WALLED_GARDEN_PATTERN));
mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
DEFAULT_WALLED_GARDEN_INTERVAL_MS);
@@ -426,6 +421,9 @@
*
*/
private void resetWatchdogState() {
+ if (VDBG) {
+ Slog.v(WWSM_TAG, "Resetting watchdog state...");
+ }
mInitialConnInfo = null;
mDisableAPNextFailure = false;
mLastWalledGardenCheckTime = null;
@@ -467,6 +465,22 @@
notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning);
}
+ /**
+ * @return true if there is definitely no mobile data (we'll be less aggressive)
+ */
+ private boolean hasNoMobileData() {
+ if (mConnectivityManager == null) {
+ mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ }
+ NetworkInfo mobileNetInfo = mConnectivityManager.getNetworkInfo(
+ ConnectivityManager.TYPE_MOBILE);
+ if (mobileNetInfo == null || !mobileNetInfo.isAvailable()) {
+ return true;
+ }
+ return false;
+ }
+
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
@@ -521,11 +535,8 @@
switch (networkInfo.getState()) {
case CONNECTED:
- // WifiInfo wifiInfo = (WifiInfo)
- // stateChangeIntent
- // .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
- // TODO : Replace with above code when API is changed
- WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ WifiInfo wifiInfo = (WifiInfo)
+ stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (wifiInfo == null) {
Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!");
return HANDLED;
@@ -848,6 +859,7 @@
}
class DnsCheckFailureState extends State {
+
@Override
public void enter() {
mNumCheckFailures++;
@@ -868,6 +880,13 @@
}
if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) {
+ if (hasNoMobileData()) {
+ Slog.w(WWSM_TAG, "Would disable bad network, but device has no mobile data!" +
+ " Going idle...");
+ // This state should be called idle -- will be changing flow.
+ transitionTo(mNotConnectedState);
+ return HANDLED;
+ }
// TODO : Unban networks if they had low signal ?
Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo)
+ ". " + "numCheckFailures " + mNumCheckFailures