diff options
273 files changed, 2480 insertions, 1113 deletions
@@ -450,7 +450,9 @@ web_docs_sample_code_flags := \ -samplecode $(sample_dir)/VoicemailProviderDemo \ resources/samples/VoicemailProviderDemo "Voicemail Provider Demo" \ -samplecode $(sample_dir)/XmlAdapters \ - resources/samples/XmlAdapters "XML Adapters" + resources/samples/XmlAdapters "XML Adapters" \ + -samplecode $(sample_dir)/TtsEngine \ + resources/samples/TtsEngine "Text To Speech Engine" ## SDK version identifiers used in the published docs # major[.minor] version for current SDK. (full releases only) diff --git a/api/current.txt b/api/current.txt index d009a64..9ad7b4e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -183,14 +183,14 @@ package android { public static final class R.attr { ctor public R.attr(); field public static final int absListViewStyle = 16842858; // 0x101006a - field public static final int accessibilityEventTypes = 16843650; // 0x1010382 - field public static final int accessibilityFeedbackType = 16843652; // 0x1010384 - field public static final int accessibilityFlags = 16843654; // 0x1010386 + field public static final int accessibilityEventTypes = 16843649; // 0x1010381 + field public static final int accessibilityFeedbackType = 16843651; // 0x1010383 + field public static final int accessibilityFlags = 16843653; // 0x1010385 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 = 16843676; // 0x101039c + field public static final int actionBarSplitStyle = 16843675; // 0x101039b field public static final int actionBarStyle = 16843470; // 0x10102ce field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4 field public static final int actionBarTabStyle = 16843507; // 0x10102f3 @@ -206,9 +206,9 @@ package android { 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 = 16843648; // 0x1010380 + field public static final int actionModeSelectAllDrawable = 16843647; // 0x101037f field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6 - field public static final int actionProviderClass = 16843678; // 0x101039e + field public static final int actionProviderClass = 16843677; // 0x101039d field public static final int actionViewClass = 16843516; // 0x10102fc field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba @@ -220,7 +220,7 @@ package android { field public static final int alertDialogIcon = 16843605; // 0x1010355 field public static final int alertDialogStyle = 16842845; // 0x101005d field public static final int alertDialogTheme = 16843529; // 0x1010309 - field public static final int alignmentMode = 16843642; // 0x101037a + field public static final int alignmentMode = 16843641; // 0x1010379 field public static final int allContactsName = 16843468; // 0x10102cc field public static final int allowBackup = 16843392; // 0x1010280 field public static final int allowClearUserData = 16842757; // 0x1010005 @@ -254,6 +254,8 @@ package android { 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 = 16843679; // 0x101039f + field public static final int backgroundStacked = 16843678; // 0x101039e field public static final int backupAgent = 16843391; // 0x101027f field public static final int baseline = 16843548; // 0x101031c field public static final int baselineAlignBottom = 16843042; // 0x1010122 @@ -262,7 +264,7 @@ package android { 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 = 16843661; // 0x101038d + field public static final int bottomChevronDrawable = 16843660; // 0x101038c field public static final int bottomDark = 16842953; // 0x10100c9 field public static final int bottomLeftRadius = 16843179; // 0x10101ab field public static final int bottomMedium = 16842958; // 0x10100ce @@ -281,7 +283,7 @@ package android { 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 = 16843655; // 0x1010387 + field public static final int canRetrieveWindowContent = 16843654; // 0x1010386 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 @@ -314,9 +316,9 @@ package android { field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab field public static final int colorForeground = 16842800; // 0x1010030 field public static final int colorForegroundInverse = 16843270; // 0x1010206 - field public static final int columnCount = 16843639; // 0x1010377 + field public static final int columnCount = 16843638; // 0x1010376 field public static final int columnDelay = 16843215; // 0x10101cf - field public static final int columnOrderPreserved = 16843640; // 0x1010378 + field public static final int columnOrderPreserved = 16843639; // 0x1010377 field public static final int columnWidth = 16843031; // 0x1010117 field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365 field public static final int completionHint = 16843122; // 0x1010172 @@ -429,7 +431,7 @@ package android { 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 = 16843667; // 0x1010393 + field public static final int feedbackCount = 16843666; // 0x1010392 field public static final int fillAfter = 16843197; // 0x10101bd field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillEnabled = 16843343; // 0x101024f @@ -462,7 +464,6 @@ package android { field public static final int fromXScale = 16843202; // 0x10101c2 field public static final int fromYDelta = 16843208; // 0x10101c8 field public static final int fromYScale = 16843204; // 0x10101c4 - field public static final int fullBackupAgent = 16843635; // 0x1010373 field public static final int fullBright = 16842954; // 0x10100ca field public static final int fullDark = 16842950; // 0x10100c6 field public static final int functionalTest = 16842787; // 0x1010023 @@ -483,7 +484,7 @@ package android { 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 = 16843657; // 0x1010389 + field public static final int handleDrawable = 16843656; // 0x1010388 field public static final int handleProfiling = 16842786; // 0x1010022 field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e field public static final int hardwareAccelerated = 16843475; // 0x10102d3 @@ -492,12 +493,12 @@ package android { 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 = 16843664; // 0x1010390 + field public static final int hitRadius = 16843663; // 0x101038f 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 = 16843669; // 0x1010395 + field public static final int horizontalOffset = 16843668; // 0x1010394 field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353 field public static final int horizontalSpacing = 16843028; // 0x1010114 field public static final int host = 16842792; // 0x1010028 @@ -543,7 +544,7 @@ package android { 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 = 16843649; // 0x1010381 + field public static final int isAuxiliary = 16843648; // 0x1010380 field public static final int isDefault = 16843297; // 0x1010221 field public static final int isIndicator = 16843079; // 0x1010147 field public static final int isModifier = 16843334; // 0x1010246 @@ -597,30 +598,30 @@ package android { 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_columnSpan = 16843645; // 0x101037d + field public static final int layout_columnSpan = 16843644; // 0x101037c field public static final int layout_gravity = 16842931; // 0x10100b3 field public static final int layout_height = 16842997; // 0x10100f5 - field public static final int layout_heightSpec = 16843647; // 0x101037f + field public static final int layout_heightSpec = 16843646; // 0x101037e field public static final int layout_margin = 16842998; // 0x10100f6 field public static final int layout_marginBottom = 16843002; // 0x10100fa - field public static final int layout_marginEnd = 16843675; // 0x101039b + field public static final int layout_marginEnd = 16843674; // 0x101039a field public static final int layout_marginLeft = 16842999; // 0x10100f7 field public static final int layout_marginRight = 16843001; // 0x10100f9 - field public static final int layout_marginStart = 16843674; // 0x101039a + field public static final int layout_marginStart = 16843673; // 0x1010399 field public static final int layout_marginTop = 16843000; // 0x10100f8 - field public static final int layout_row = 16843643; // 0x101037b - field public static final int layout_rowSpan = 16843644; // 0x101037c + field public static final int layout_row = 16843642; // 0x101037a + field public static final int layout_rowSpan = 16843643; // 0x101037b 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 field public static final int layout_toRightOf = 16843139; // 0x1010183 field public static final int layout_weight = 16843137; // 0x1010181 field public static final int layout_width = 16842996; // 0x10100f4 - field public static final int layout_widthSpec = 16843646; // 0x101037e + field public static final int layout_widthSpec = 16843645; // 0x101037d 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 = 16843658; // 0x101038a + field public static final int leftChevronDrawable = 16843657; // 0x1010389 field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 field public static final int lines = 16843092; // 0x1010154 @@ -632,8 +633,8 @@ package android { field public static final int listDividerAlertDialog = 16843525; // 0x1010305 field public static final int listPopupWindowStyle = 16843519; // 0x10102ff field public static final int listPreferredItemHeight = 16842829; // 0x101004d - field public static final int listPreferredItemHeightLarge = 16843670; // 0x1010396 - field public static final int listPreferredItemHeightSmall = 16843671; // 0x1010397 + field public static final int listPreferredItemHeightLarge = 16843669; // 0x1010395 + field public static final int listPreferredItemHeightSmall = 16843670; // 0x1010396 field public static final int listSelector = 16843003; // 0x10100fb field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208 field public static final int listViewStyle = 16842868; // 0x1010074 @@ -679,7 +680,7 @@ package android { 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 = 16843653; // 0x1010385 + field public static final int notificationTimeout = 16843652; // 0x1010384 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 @@ -693,17 +694,17 @@ package android { 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 = 16843663; // 0x101038f + field public static final int outerRadius = 16843662; // 0x101038e 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 = 16843651; // 0x1010383 + field public static final int packageNames = 16843650; // 0x1010382 field public static final int padding = 16842965; // 0x10100d5 field public static final int paddingBottom = 16842969; // 0x10100d9 - field public static final int paddingEnd = 16843673; // 0x1010399 + field public static final int paddingEnd = 16843672; // 0x1010398 field public static final int paddingLeft = 16842966; // 0x10100d6 field public static final int paddingRight = 16842968; // 0x10100d8 - field public static final int paddingStart = 16843672; // 0x1010398 + field public static final int paddingStart = 16843671; // 0x1010397 field public static final int paddingTop = 16842967; // 0x10100d7 field public static final int panelBackground = 16842846; // 0x101005e field public static final int panelColorBackground = 16842849; // 0x1010061 @@ -784,17 +785,17 @@ package android { 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 = 16843659; // 0x101038b + field public static final int rightChevronDrawable = 16843658; // 0x101038a 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 = 16843637; // 0x1010375 + field public static final int rowCount = 16843636; // 0x1010374 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 = 16843638; // 0x1010376 + field public static final int rowOrderPreserved = 16843637; // 0x1010375 field public static final int saveEnabled = 16842983; // 0x10100e7 field public static final int scaleGravity = 16843262; // 0x10101fe field public static final int scaleHeight = 16843261; // 0x10101fd @@ -860,7 +861,7 @@ package android { 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 = 16843666; // 0x1010392 + field public static final int snapMargin = 16843665; // 0x1010391 field public static final int soundEffectsEnabled = 16843285; // 0x1010215 field public static final int spacing = 16843027; // 0x1010113 field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087 @@ -908,7 +909,7 @@ package android { 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 = 16843636; // 0x1010374 + field public static final int suggestionsEnabled = 16843635; // 0x1010373 field public static final int summary = 16843241; // 0x10101e9 field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 @@ -925,7 +926,7 @@ package android { 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 = 16843656; // 0x1010388 + field public static final int targetDrawables = 16843655; // 0x1010387 field public static final int targetPackage = 16842785; // 0x1010021 field public static final int targetSdkVersion = 16843376; // 0x1010270 field public static final int taskAffinity = 16842770; // 0x1010012 @@ -976,7 +977,7 @@ package android { field public static final int textColorTertiary = 16843282; // 0x1010212 field public static final int textColorTertiaryInverse = 16843283; // 0x1010213 field public static final int textCursorDrawable = 16843618; // 0x1010362 - field public static final int textDirection = 16843677; // 0x101039d + field public static final int textDirection = 16843676; // 0x101039c field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315 field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314 field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f @@ -1016,7 +1017,7 @@ package android { 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 = 16843660; // 0x101038c + field public static final int topChevronDrawable = 16843659; // 0x101038b field public static final int topDark = 16842951; // 0x10100c7 field public static final int topLeftRadius = 16843177; // 0x10101a9 field public static final int topOffset = 16843352; // 0x1010258 @@ -1032,7 +1033,7 @@ package android { 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 = 16843641; // 0x1010379 + field public static final int useDefaultMargins = 16843640; // 0x1010378 field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310 field public static final int useLevel = 16843167; // 0x101019f field public static final int userVisible = 16843409; // 0x1010291 @@ -1046,10 +1047,10 @@ package android { 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 = 16843668; // 0x1010394 + field public static final int verticalOffset = 16843667; // 0x1010393 field public static final int verticalScrollbarPosition = 16843572; // 0x1010334 field public static final int verticalSpacing = 16843029; // 0x1010115 - field public static final int vibrationDuration = 16843665; // 0x1010391 + field public static final int vibrationDuration = 16843664; // 0x1010390 field public static final int visibility = 16842972; // 0x10100dc field public static final int visible = 16843156; // 0x1010194 field public static final int vmSafeMode = 16843448; // 0x10102b8 @@ -1066,7 +1067,7 @@ package android { 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 = 16843662; // 0x101038e + field public static final int waveDrawable = 16843661; // 0x101038d field public static final int webTextViewStyle = 16843449; // 0x10102b9 field public static final int webViewStyle = 16842885; // 0x1010085 field public static final int weekDayTextAppearance = 16843592; // 0x1010348 @@ -1512,9 +1513,13 @@ package android { field public static final int TextAppearance_Holo_Small_Inverse = 16974082; // 0x1030102 field public static final int TextAppearance_Holo_Widget = 16974085; // 0x1030105 field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle = 16974099; // 0x1030113 + field public static final int TextAppearance_Holo_Widget_ActionBar_Subtitle_Inverse = 16974110; // 0x103011e field public static final int TextAppearance_Holo_Widget_ActionBar_Title = 16974098; // 0x1030112 + field public static final int TextAppearance_Holo_Widget_ActionBar_Title_Inverse = 16974109; // 0x103011d field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle = 16974101; // 0x1030115 + field public static final int TextAppearance_Holo_Widget_ActionMode_Subtitle_Inverse = 16974112; // 0x1030120 field public static final int TextAppearance_Holo_Widget_ActionMode_Title = 16974100; // 0x1030114 + field public static final int TextAppearance_Holo_Widget_ActionMode_Title_Inverse = 16974111; // 0x103011f field public static final int TextAppearance_Holo_Widget_Button = 16974086; // 0x1030106 field public static final int TextAppearance_Holo_Widget_DropDownHint = 16974091; // 0x103010b field public static final int TextAppearance_Holo_Widget_DropDownItem = 16974092; // 0x103010c @@ -1577,10 +1582,16 @@ package android { field public static final int Theme_Holo_Light_NoActionBar = 16974064; // 0x10300f0 field public static final int Theme_Holo_Light_NoActionBar_Fullscreen = 16974065; // 0x10300f1 field public static final int Theme_Holo_Light_Panel = 16973948; // 0x103007c + field public static final int Theme_Holo_Light_SolidActionBar = 16974121; // 0x1030129 + field public static final int Theme_Holo_Light_SolidActionBar_Inverse = 16974122; // 0x103012a + field public static final int Theme_Holo_Light_SolidActionBar_Inverse_SplitActionBarWhenNarrow = 16974125; // 0x103012d + field public static final int Theme_Holo_Light_SolidActionBar_SplitActionBarWhenNarrow = 16974124; // 0x103012c field public static final int Theme_Holo_Light_SplitActionBarWhenNarrow = 16974106; // 0x103011a field public static final int Theme_Holo_NoActionBar = 16973932; // 0x103006c field public static final int Theme_Holo_NoActionBar_Fullscreen = 16973933; // 0x103006d field public static final int Theme_Holo_Panel = 16973947; // 0x103007b + field public static final int Theme_Holo_SolidActionBar = 16974120; // 0x1030128 + field public static final int Theme_Holo_SolidActionBar_SplitActionBarWhenNarrow = 16974123; // 0x103012b field public static final int Theme_Holo_SplitActionBarWhenNarrow = 16974105; // 0x1030119 field public static final int Theme_Holo_Wallpaper = 16973949; // 0x103007d field public static final int Theme_Holo_Wallpaper_NoTitleBar = 16973950; // 0x103007e @@ -1632,6 +1643,7 @@ package android { field public static final int Widget_GridView = 16973874; // 0x1030032 field public static final int Widget_Holo = 16973962; // 0x103008a field public static final int Widget_Holo_ActionBar = 16974004; // 0x10300b4 + field public static final int Widget_Holo_ActionBar_Solid = 16974113; // 0x1030121 field public static final int Widget_Holo_ActionBar_TabBar = 16974071; // 0x10300f7 field public static final int Widget_Holo_ActionBar_TabText = 16974070; // 0x10300f6 field public static final int Widget_Holo_ActionBar_TabView = 16974069; // 0x10300f5 @@ -1661,13 +1673,19 @@ package android { field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096 field public static final int Widget_Holo_Light = 16974005; // 0x10300b5 field public static final int Widget_Holo_Light_ActionBar = 16974049; // 0x10300e1 + field public static final int Widget_Holo_Light_ActionBar_Solid = 16974114; // 0x1030122 + field public static final int Widget_Holo_Light_ActionBar_Solid_Inverse = 16974115; // 0x1030123 field public static final int Widget_Holo_Light_ActionBar_TabBar = 16974074; // 0x10300fa + field public static final int Widget_Holo_Light_ActionBar_TabBar_Inverse = 16974116; // 0x1030124 field public static final int Widget_Holo_Light_ActionBar_TabText = 16974073; // 0x10300f9 + field public static final int Widget_Holo_Light_ActionBar_TabText_Inverse = 16974118; // 0x1030126 field public static final int Widget_Holo_Light_ActionBar_TabView = 16974072; // 0x10300f8 + field public static final int Widget_Holo_Light_ActionBar_TabView_Inverse = 16974117; // 0x1030125 field public static final int Widget_Holo_Light_ActionButton = 16974045; // 0x10300dd field public static final int Widget_Holo_Light_ActionButton_CloseMode = 16974048; // 0x10300e0 field public static final int Widget_Holo_Light_ActionButton_Overflow = 16974046; // 0x10300de field public static final int Widget_Holo_Light_ActionMode = 16974047; // 0x10300df + field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127 field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6 field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974108; // 0x103011c @@ -3737,7 +3755,11 @@ package android.app.backup { method public abstract void onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor) throws java.io.IOException; method public void onCreate(); method public void onDestroy(); + method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException; method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException; + method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException; + field public static final int TYPE_DIRECTORY = 2; // 0x2 + field public static final int TYPE_FILE = 1; // 0x1 } public class BackupAgentHelper extends android.app.backup.BackupAgent { @@ -3789,6 +3811,9 @@ package android.app.backup { method public void writeNewStateDescription(android.os.ParcelFileDescriptor); } + public class FullBackupDataOutput { + } + public abstract class RestoreObserver { ctor public RestoreObserver(); method public void onUpdate(int, java.lang.String); @@ -17509,8 +17534,12 @@ package android.security { public final class KeyChain { ctor public KeyChain(); method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String); + method public static android.content.Intent createInstallIntent(); method public static java.security.cert.X509Certificate[] getCertificateChain(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException; method public static java.security.PrivateKey getPrivateKey(android.content.Context, java.lang.String) throws java.lang.InterruptedException, android.security.KeyChainException; + field public static final java.lang.String EXTRA_CERTIFICATE = "CERT"; + field public static final java.lang.String EXTRA_NAME = "name"; + field public static final java.lang.String EXTRA_PKCS12 = "PKCS12"; } public abstract interface KeyChainAliasCallback { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 1ec7a96..eee14fb 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2013,15 +2013,10 @@ public final class ActivityThread { BackupAgent agent = null; String classname = data.appInfo.backupAgentName; - if (data.backupMode == IApplicationThread.BACKUP_MODE_FULL - || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL) { + // full backup operation but no app-supplied agent? use the default implementation + if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL + || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) { classname = "android.app.backup.FullBackupAgent"; - if ((data.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { - // system packages can supply their own full-backup agent - if (data.appInfo.fullBackupAgentName != null) { - classname = data.appInfo.fullBackupAgentName; - } - } } try { diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl index 8af78fa..087f83c 100644 --- a/core/java/android/app/IBackupAgent.aidl +++ b/core/java/android/app/IBackupAgent.aidl @@ -51,7 +51,6 @@ oneway interface IBackupAgent { void doBackup(in ParcelFileDescriptor oldState, in ParcelFileDescriptor data, in ParcelFileDescriptor newState, - boolean storeApk, int token, IBackupManager callbackBinder); /** @@ -81,6 +80,25 @@ oneway interface IBackupAgent { in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder); /** + * Perform a "full" backup to the given file descriptor. The output file is presumed + * to be a socket or other non-seekable, write-only data sink. When this method is + * called, the app should write all of its files to the output. + * + * @param data Write-only file to receive the backed-up file content stream. + * The data must be formatted correctly for the resulting archive to be + * legitimate, so that will be tightly controlled by the available API. + * + * @param token Opaque token identifying this transaction. This must + * be echoed back to the backup service binder once the agent is + * finished restoring the application based on the restore data + * contents. + * + * @param callbackBinder Binder on which to indicate operation completion, + * passed here as a convenience to the agent. + */ + void doFullBackup(in ParcelFileDescriptor data, int token, IBackupManager callbackBinder); + + /** * Restore a single "file" to the application. The file was typically obtained from * a full-backup dataset. The agent reads 'size' bytes of file content * from the provided file descriptor. diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 63f3258..dce0a97 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -20,13 +20,22 @@ import android.app.IBackupAgent; import android.app.backup.IBackupManager; import android.content.Context; import android.content.ContextWrapper; +import android.content.pm.ApplicationInfo; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; +import java.io.File; import java.io.IOException; +import java.util.HashSet; +import java.util.LinkedList; + +import libcore.io.ErrnoException; +import libcore.io.Libcore; +import libcore.io.OsConstants; +import libcore.io.StructStat; /** * Provides the central interface between an @@ -87,6 +96,24 @@ public abstract class BackupAgent extends ContextWrapper { private static final String TAG = "BackupAgent"; private static final boolean DEBUG = true; + /** @hide */ + public static final int TYPE_EOF = 0; + + /** + * During a full restore, indicates that the file system object being restored + * is an ordinary file. + */ + public static final int TYPE_FILE = 1; + + /** + * During a full restore, indicates that the file system object being restored + * is a directory. + */ + public static final int TYPE_DIRECTORY = 2; + + /** @hide */ + public static final int TYPE_SYMLINK = 3; + public BackupAgent() { super(null); } @@ -179,18 +206,240 @@ public abstract class BackupAgent extends ContextWrapper { throws IOException; /** + * The default implementation backs up the entirety of the application's "owned" + * file system trees to the output. + */ + 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 libDir = (appInfo.nativeLibraryDir != null) + ? new File(appInfo.nativeLibraryDir).getAbsolutePath() + : null; + + // Filters, the scan queue, and the set of resulting entities + HashSet<String> filterSet = new HashSet<String>(); + String packageName = getPackageName(); + + // Okay, start with the app's root tree, but exclude all of the canonical subdirs + if (libDir != null) { + filterSet.add(libDir); + } + filterSet.add(cacheDir); + filterSet.add(databaseDir); + filterSet.add(sharedPrefsDir); + filterSet.add(filesDir); + fullBackupFileTree(packageName, FullBackup.ROOT_TREE_TOKEN, rootDir, filterSet, data); + + // Now do the same for the files dir, db dir, and shared prefs dir + filterSet.add(rootDir); + filterSet.remove(filesDir); + fullBackupFileTree(packageName, FullBackup.DATA_TREE_TOKEN, filesDir, filterSet, data); + + filterSet.add(filesDir); + filterSet.remove(databaseDir); + fullBackupFileTree(packageName, FullBackup.DATABASE_TREE_TOKEN, databaseDir, filterSet, data); + + filterSet.add(databaseDir); + filterSet.remove(sharedPrefsDir); + fullBackupFileTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, sharedPrefsDir, filterSet, data); + } + + /** + * Write an entire file as part of a full-backup operation. The file's contents + * will be delivered to the backup destination along with the metadata necessary + * to place it with the proper location and permissions on the device where the + * data is restored. * @hide + * + * @param context The BackupAgent that is calling this method. It is an error to + * call it from something other than a running BackupAgent instance. + * @param file The file to be backed up. The file must exist and be readable by + * the caller. + * @param output The destination to which the backed-up file data will be sent. + */ + public final void fullBackupFile(File file, FullBackupDataOutput output) { + // Look up where all of our various well-defined dir trees live on this device + String mainDir; + String filesDir; + String dbDir; + String spDir; + String cacheDir; + String libDir; + + 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(); + + // 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(); + + if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) { + Log.w(TAG, "lib and cache files are not backed up"); + return; + } + + final String domain; + String rootpath = null; + if (filePath.startsWith(dbDir)) { + domain = FullBackup.DATABASE_TREE_TOKEN; + rootpath = dbDir; + } else if (filePath.startsWith(spDir)) { + domain = FullBackup.SHAREDPREFS_TREE_TOKEN; + rootpath = spDir; + } else if (filePath.startsWith(filesDir)) { + domain = FullBackup.DATA_TREE_TOKEN; + rootpath = filesDir; + } else if (filePath.startsWith(mainDir)) { + domain = FullBackup.ROOT_TREE_TOKEN; + rootpath = mainDir; + } else { + Log.w(TAG, "File " + filePath + " is in an unsupported location; skipping"); + return; + } + + // And now that we know where it lives, semantically, back it up appropriately + Log.i(TAG, "backupFile() of " + filePath + " => domain=" + domain + + " rootpath=" + rootpath); + FullBackup.backupToTar(getPackageName(), domain, null, rootpath, filePath, + output.getData()); + } + + /** + * Scan the dir tree (if it actually exists) and process each entry we find. If the + * 'excludes' parameter is non-null, it is consulted each time a new file system entity + * is visited to see whether that entity (and its subtree, if appropriate) should be + * omitted from the backup process. + * + * @hide + */ + protected final void fullBackupFileTree(String packageName, String domain, String rootPath, + HashSet<String> excludes, FullBackupDataOutput output) { + File rootFile = new File(rootPath); + if (rootFile.exists()) { + LinkedList<File> scanQueue = new LinkedList<File>(); + scanQueue.add(rootFile); + + 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. + try { + StructStat stat = Libcore.os.lstat(filePath); + if (OsConstants.S_ISLNK(stat.st_mode)) { + if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file); + continue; + } else if (OsConstants.S_ISDIR(stat.st_mode)) { + File[] contents = file.listFiles(); + if (contents != null) { + for (File entry : contents) { + scanQueue.add(0, entry); + } + } + } + } catch (ErrnoException e) { + if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e); + continue; + } + + // Finally, back this file up before proceeding + FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, + output.getData()); + } + } + } + + /** + * Handle the data delivered via the given file descriptor during a full restore + * operation. The agent is given the path to the file's original location as well + * as its size and metadata. + * <p> + * The file descriptor can only be read for {@code size} bytes; attempting to read + * more data has undefined behavior. + * <p> + * The default implementation creates the destination file/directory and populates it + * with the data from the file descriptor, then sets the file's access mode and + * modification time to match the restore arguments. + * + * @param data A read-only file descriptor from which the agent can read {@code size} + * bytes of file data. + * @param size The number of bytes of file content to be restored to the given + * destination. If the file system object being restored is a directory, {@code size} + * will be zero. + * @param destination The File on disk to be restored with the given data. + * @param type The kind of file system object being restored. This will be either + * {@link BackupAgent#TYPE_FILE} or {@link BackupAgent#TYPE_DIRECTORY}. + * @param mode The access mode to be assigned to the destination after its data is + * written. This is in the standard format used by {@code chmod()}. + * @param mtime The modification time of the file when it was backed up, suitable to + * be assigned to the file after its data is written. + * @throws IOException */ public void onRestoreFile(ParcelFileDescriptor data, long size, - int type, String domain, String path, long mode, long mtime) + File destination, int type, long mode, long mtime) throws IOException { - // empty stub implementation + FullBackup.restoreFile(data, size, type, mode, mtime, destination); } /** - * Package-private, used only for dispatching an extra step during full backup + * Only specialized platform agents should overload this entry point to support + * restores to crazy non-app locations. + * @hide */ - void onSaveApk(BackupDataOutput data) { + protected void onRestoreFile(ParcelFileDescriptor data, long size, + int type, String domain, String path, long mode, long mtime) + throws IOException { + String basePath = null; + + if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type + + " domain=" + domain + " relpath=" + path + " mode=" + mode + + " mtime=" + mtime); + + // Parse out the semantic domains into the correct physical location + if (domain.equals(FullBackup.DATA_TREE_TOKEN)) { + basePath = getFilesDir().getAbsolutePath(); + } else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) { + basePath = getDatabasePath("foo").getParentFile().getAbsolutePath(); + } else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) { + basePath = new File(getApplicationInfo().dataDir).getAbsolutePath(); + } else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) { + basePath = getSharedPrefsFile("foo").getParentFile().getAbsolutePath(); + } else if (domain.equals(FullBackup.CACHE_TREE_TOKEN)) { + basePath = getCacheDir().getAbsolutePath(); + } else { + // Not a supported location + Log.i(TAG, "Data restored from non-app domain " + domain + ", ignoring"); + } + + // Now that we've figured out where the data goes, send it on its way + if (basePath != null) { + File outFile = new File(basePath, path); + if (DEBUG) Log.i(TAG, "[" + domain + " : " + path + "] mapped to " + outFile.getPath()); + onRestoreFile(data, size, outFile, type, mode, mtime); + } else { + // Not a supported output location? We need to consume the data + // anyway, so just use the default "copy the data out" implementation + // with a null destination. + if (DEBUG) Log.i(TAG, "[ skipping data from unsupported domain " + domain + "]"); + FullBackup.restoreFile(data, size, type, mode, mtime, null); + } } // ----- Core implementation ----- @@ -215,7 +464,6 @@ public abstract class BackupAgent extends ContextWrapper { public void doBackup(ParcelFileDescriptor oldState, ParcelFileDescriptor data, ParcelFileDescriptor newState, - boolean storeApk, int token, IBackupManager callbackBinder) throws RemoteException { // Ensure that we're running with the app's normal permission level long ident = Binder.clearCallingIdentity(); @@ -223,10 +471,6 @@ public abstract class BackupAgent extends ContextWrapper { if (DEBUG) Log.v(TAG, "doBackup() invoked"); BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor()); - if (storeApk) { - onSaveApk(output); - } - try { BackupAgent.this.onBackup(oldState, output, newState); } catch (IOException ex) { @@ -273,6 +517,32 @@ public abstract class BackupAgent extends ContextWrapper { } @Override + public void doFullBackup(ParcelFileDescriptor data, + int token, IBackupManager callbackBinder) { + // Ensure that we're running with the app's normal permission level + long ident = Binder.clearCallingIdentity(); + + if (DEBUG) Log.v(TAG, "doFullBackup() invoked"); + + try { + BackupAgent.this.onFullBackup(new FullBackupDataOutput(data)); + } catch (IOException ex) { + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw new RuntimeException(ex); + } catch (RuntimeException ex) { + Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); + throw ex; + } finally { + Binder.restoreCallingIdentity(ident); + try { + callbackBinder.opComplete(token); + } catch (RemoteException e) { + // we'll time out anyway, so we're safe + } + } + } + + @Override public void doRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String path, long mode, long mtime, int token, IBackupManager callbackBinder) throws RemoteException { diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 3b70e19..d7f1c9f 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -16,6 +16,9 @@ package android.app.backup; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -29,7 +32,8 @@ import libcore.io.Libcore; /** * Global constant definitions et cetera related to the full-backup-to-fd - * binary format. + * binary format. Nothing in this namespace is part of any API; it's all + * hidden details of the current implementation gathered into one location. * * @hide */ @@ -52,18 +56,41 @@ public class FullBackup { public static final String FULL_RESTORE_INTENT_ACTION = "fullrest"; public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken"; - public static final int TYPE_EOF = 0; - public static final int TYPE_FILE = 1; - public static final int TYPE_DIRECTORY = 2; - public static final int TYPE_SYMLINK = 3; - + /** + * @hide + */ static public native int backupToTar(String packageName, String domain, String linkdomain, String rootpath, String path, BackupDataOutput output); - static public void restoreToFile(ParcelFileDescriptor data, - long size, int type, long mode, long mtime, File outFile, - boolean doChmod) throws IOException { - if (type == FullBackup.TYPE_DIRECTORY) { + /** + * Copy data from a socket to the given File location on permanent storage. The + * modification time and access mode of the resulting file will be set if desired. + * If the {@code type} parameter indicates that the result should be a directory, + * the socket parameter may be {@code null}; even if it is valid, no data will be + * read from it in this case. + * <p> + * If the {@code mode} argument is negative, then the resulting output file will not + * have its access mode or last modification time reset as part of this operation. + * + * @param data Socket supplying the data to be copied to the output file. If the + * output is a directory, this may be {@code null}. + * @param size Number of bytes of data to copy from the socket to the file. At least + * this much data must be available through the {@code data} parameter. + * @param type Must be either {@link BackupAgent#TYPE_FILE} for ordinary file data + * or {@link BackupAgent#TYPE_DIRECTORY} for a directory. + * @param mode Unix-style file mode (as used by the chmod(2) syscall) to be set on + * the output file or directory. If this parameter is negative then neither + * the mode nor the mtime parameters will be used. + * @param mtime A timestamp in the standard Unix epoch that will be imposed as the + * last modification time of the output file. if the {@code mode} parameter is + * negative then this parameter will be ignored. + * @param outFile Location within the filesystem to place the data. This must point + * to a location that is writeable by the caller, prefereably using an absolute path. + * @throws IOException + */ + static public void restoreFile(ParcelFileDescriptor data, + long size, int type, long mode, long mtime, File outFile) throws IOException { + if (type == BackupAgent.TYPE_DIRECTORY) { // Canonically a directory has no associated content, so we don't need to read // anything from the pipe in this case. Just create the directory here and // drop down to the final metadata adjustment. @@ -117,7 +144,7 @@ public class FullBackup { } // Now twiddle the state to match the backup, assuming all went well - if (doChmod && outFile != null) { + if (mode >= 0 && outFile != null) { try { Libcore.os.chmod(outFile.getPath(), (int)mode); } catch (ErrnoException e) { diff --git a/core/java/android/app/backup/FullBackupAgent.java b/core/java/android/app/backup/FullBackupAgent.java index df1c363..faea76a 100644 --- a/core/java/android/app/backup/FullBackupAgent.java +++ b/core/java/android/app/backup/FullBackupAgent.java @@ -16,210 +16,26 @@ package android.app.backup; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.os.Environment; import android.os.ParcelFileDescriptor; -import android.util.Log; - -import libcore.io.Libcore; -import libcore.io.ErrnoException; -import libcore.io.OsConstants; -import libcore.io.StructStat; - -import java.io.File; import java.io.IOException; -import java.util.HashSet; -import java.util.LinkedList; /** - * Backs up an application's entire /data/data/<package>/... file system. This - * class is used by the desktop full backup mechanism and is not intended for direct - * use by applications. + * Simple concrete class that merely provides the default BackupAgent full backup/restore + * implementations for applications that do not supply their own. * * {@hide} */ public class FullBackupAgent extends BackupAgent { - // !!! TODO: turn off debugging - private static final String TAG = "FullBackupAgent"; - private static final boolean DEBUG = true; - - PackageManager mPm; - - private String mMainDir; - private String mFilesDir; - private String mDatabaseDir; - private String mSharedPrefsDir; - private String mCacheDir; - private String mLibDir; - - private File NULL_FILE; - - @Override - public void onCreate() { - NULL_FILE = new File("/dev/null"); - - mPm = getPackageManager(); - try { - ApplicationInfo appInfo = mPm.getApplicationInfo(getPackageName(), 0); - mMainDir = new File(appInfo.dataDir).getAbsolutePath(); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Unable to find package " + getPackageName()); - throw new RuntimeException(e); - } - - mFilesDir = getFilesDir().getAbsolutePath(); - mDatabaseDir = getDatabasePath("foo").getParentFile().getAbsolutePath(); - mSharedPrefsDir = getSharedPrefsFile("foo").getParentFile().getAbsolutePath(); - mCacheDir = getCacheDir().getAbsolutePath(); - - ApplicationInfo app = getApplicationInfo(); - mLibDir = (app.nativeLibraryDir != null) - ? new File(app.nativeLibraryDir).getAbsolutePath() - : null; - } - @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { - // Filters, the scan queue, and the set of resulting entities - HashSet<String> filterSet = new HashSet<String>(); - String packageName = getPackageName(); - - // Okay, start with the app's root tree, but exclude all of the canonical subdirs - if (mLibDir != null) { - filterSet.add(mLibDir); - } - filterSet.add(mCacheDir); - filterSet.add(mDatabaseDir); - filterSet.add(mSharedPrefsDir); - filterSet.add(mFilesDir); - processTree(packageName, FullBackup.ROOT_TREE_TOKEN, mMainDir, filterSet, data); - - // Now do the same for the files dir, db dir, and shared prefs dir - filterSet.add(mMainDir); - filterSet.remove(mFilesDir); - processTree(packageName, FullBackup.DATA_TREE_TOKEN, mFilesDir, filterSet, data); - - filterSet.add(mFilesDir); - filterSet.remove(mDatabaseDir); - processTree(packageName, FullBackup.DATABASE_TREE_TOKEN, mDatabaseDir, filterSet, data); - - filterSet.add(mDatabaseDir); - filterSet.remove(mSharedPrefsDir); - processTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, mSharedPrefsDir, filterSet, data); + // Doesn't do incremental backup/restore } - // Scan the dir tree (if it actually exists) and process each entry we find. If the - // 'excludes' parameter is non-null, it is consulted each time a new file system entity - // is visited to see whether that entity (and its subtree, if appropriate) should be - // omitted from the backup process. - protected void processTree(String packageName, String domain, String rootPath, - HashSet<String> excludes, BackupDataOutput data) { - File rootFile = new File(rootPath); - if (rootFile.exists()) { - LinkedList<File> scanQueue = new LinkedList<File>(); - scanQueue.add(rootFile); - - 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. - try { - StructStat stat = Libcore.os.lstat(filePath); - if (OsConstants.S_ISLNK(stat.st_mode)) { - if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file); - continue; - } else if (OsConstants.S_ISDIR(stat.st_mode)) { - File[] contents = file.listFiles(); - if (contents != null) { - for (File entry : contents) { - scanQueue.add(0, entry); - } - } - } - } catch (ErrnoException e) { - if (DEBUG) Log.w(TAG, "Error scanning file " + file + " : " + e); - continue; - } - - // Finally, back this file up before proceeding - FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, data); - } - } - } - - @Override - void onSaveApk(BackupDataOutput data) { - ApplicationInfo app = getApplicationInfo(); - if (DEBUG) Log.i(TAG, "APK flags: system=" + ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) - + " updated=" + ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) - + " locked=" + ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0) ); - if (DEBUG) Log.i(TAG, "codepath: " + getPackageCodePath()); - - // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here - final String pkgName = getPackageName(); - final String apkDir = new File(getPackageCodePath()).getParent(); - FullBackup.backupToTar(pkgName, FullBackup.APK_TREE_TOKEN, null, - apkDir, getPackageCodePath(), data); - - // Save associated .obb content if it exists and we did save the apk - // check for .obb and save those too - final File obbDir = Environment.getExternalStorageAppObbDirectory(pkgName); - if (obbDir != null) { - if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); - File[] obbFiles = obbDir.listFiles(); - if (obbFiles != null) { - final String obbDirName = obbDir.getAbsolutePath(); - for (File obb : obbFiles) { - FullBackup.backupToTar(pkgName, FullBackup.OBB_TREE_TOKEN, null, - obbDirName, obb.getAbsolutePath(), data); - } - } - } - } - - /** - * Dummy -- We're never used for restore of an incremental dataset - */ @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { - } - - /** - * Restore the described file from the given pipe. - */ - @Override - public void onRestoreFile(ParcelFileDescriptor data, long size, - int type, String domain, String relpath, long mode, long mtime) - throws IOException { - String basePath = null; - File outFile = null; - - if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type - + " domain=" + domain + " relpath=" + relpath + " mode=" + mode - + " mtime=" + mtime); - - // Parse out the semantic domains into the correct physical location - if (domain.equals(FullBackup.DATA_TREE_TOKEN)) basePath = mFilesDir; - else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) basePath = mDatabaseDir; - else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) basePath = mMainDir; - else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) basePath = mSharedPrefsDir; - - // Not a supported output location? We need to consume the data - // anyway, so send it to /dev/null - outFile = (basePath != null) ? new File(basePath, relpath) : null; - if (DEBUG) Log.i(TAG, "[" + domain + " : " + relpath + "] mapped to " + outFile.getPath()); - - // Now that we've figured out where the data goes, send it on its way - FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true); + // Doesn't do incremental backup/restore } } diff --git a/core/java/android/app/backup/FullBackupDataOutput.java b/core/java/android/app/backup/FullBackupDataOutput.java new file mode 100644 index 0000000..99dab1f --- /dev/null +++ b/core/java/android/app/backup/FullBackupDataOutput.java @@ -0,0 +1,21 @@ +package android.app.backup; + +import android.os.ParcelFileDescriptor; + +/** + * Provides the interface through which a {@link BackupAgent} writes entire files + * to a full backup data set, via its {@link BackupAgent#onFullBackup(FullBackupDataOutput)} + * method. + */ +public class FullBackupDataOutput { + // Currently a name-scoping shim around BackupDataOutput + private BackupDataOutput mData; + + /** @hide */ + public FullBackupDataOutput(ParcelFileDescriptor fd) { + mData = new BackupDataOutput(fd.getFileDescriptor()); + } + + /** @hide */ + public BackupDataOutput getData() { return mData; } +} diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 454cb31..ddb6ef0 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -91,15 +91,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String backupAgentName; /** - * Class implementing the package's *full* backup functionality. This - * is not usable except by system-installed packages. It can be the same - * as the backupAgent. - * - * @hide - */ - public String fullBackupAgentName; - - /** * Value for {@link #flags}: if set, this application is installed in the * device's system image. */ @@ -555,7 +546,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeInt(installLocation); dest.writeString(manageSpaceActivityName); dest.writeString(backupAgentName); - dest.writeString(fullBackupAgentName); dest.writeInt(descriptionRes); } @@ -593,7 +583,6 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { installLocation = source.readInt(); manageSpaceActivityName = source.readString(); backupAgentName = source.readString(); - fullBackupAgentName = source.readString(); descriptionRes = source.readInt(); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 208869b..53d6bb1 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1517,17 +1517,6 @@ public class PackageParser { } } - // fullBackupAgent is explicitly handled even if allowBackup is false - name = sa.getNonConfigurationString( - com.android.internal.R.styleable.AndroidManifestApplication_fullBackupAgent, 0); - if (name != null) { - ai.fullBackupAgentName = buildClassName(pkgName, name, outError); - if (false) { - Log.v(TAG, "android:fullBackupAgent=" + ai.fullBackupAgentName - + " from " + pkgName + "+" + name); - } - } - TypedValue v = sa.peekValue( com.android.internal.R.styleable.AndroidManifestApplication_label); if (v != null && (ai.labelRes=v.resourceId) == 0) { diff --git a/services/java/com/android/server/DnsPinger.java b/core/java/android/net/DnsPinger.java index 4e33938..f2d84eb 100644 --- a/services/java/com/android/server/DnsPinger.java +++ b/core/java/android/net/DnsPinger.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package android.net; import android.content.Context; import android.net.ConnectivityManager; diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 57f5967..d6f5643 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -23,6 +23,7 @@ import android.net.ProxyProperties; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; /** @@ -105,5 +106,7 @@ interface IConnectivityManager ParcelFileDescriptor establishVpn(in VpnConfig config); - void doLegacyVpn(in VpnConfig config, in String[] racoon, in String[] mtpd); + void startLegacyVpn(in VpnConfig config, in String[] racoon, in String[] mtpd); + + LegacyVpnInfo getLegacyVpnInfo(); } diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java index f35002a..fe6d4eb 100644 --- a/core/java/android/net/http/SslCertificate.java +++ b/core/java/android/net/http/SslCertificate.java @@ -23,13 +23,20 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import java.io.ByteArrayInputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Vector; -import com.android.org.bouncycastle.asn1.DERObjectIdentifier; import com.android.org.bouncycastle.asn1.x509.X509Name; /** @@ -45,22 +52,31 @@ public class SslCertificate { /** * Name of the entity this certificate is issued to */ - private DName mIssuedTo; + private final DName mIssuedTo; /** * Name of the entity this certificate is issued by */ - private DName mIssuedBy; + private final DName mIssuedBy; /** * Not-before date from the validity period */ - private Date mValidNotBefore; + private final Date mValidNotBefore; /** * Not-after date from the validity period */ - private Date mValidNotAfter; + private final Date mValidNotAfter; + + /** + * The original source certificate, if available. + * + * TODO If deprecated constructors are removed, this should always + * be available, and saveState and restoreState can be simplified + * to be unconditional. + */ + private final X509Certificate mX509Certificate; /** * Bundle key names @@ -69,6 +85,7 @@ public class SslCertificate { private static final String ISSUED_BY = "issued-by"; private static final String VALID_NOT_BEFORE = "valid-not-before"; private static final String VALID_NOT_AFTER = "valid-not-after"; + private static final String X509_CERTIFICATE = "x509-certificate"; /** * Saves the certificate state to a bundle @@ -76,18 +93,21 @@ public class SslCertificate { * @return A bundle with the certificate stored in it or null if fails */ public static Bundle saveState(SslCertificate certificate) { - Bundle bundle = null; - - if (certificate != null) { - bundle = new Bundle(); - - bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName()); - bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName()); - - bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore()); - bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter()); + if (certificate == null) { + return null; + } + Bundle bundle = new Bundle(); + bundle.putString(ISSUED_TO, certificate.getIssuedTo().getDName()); + bundle.putString(ISSUED_BY, certificate.getIssuedBy().getDName()); + bundle.putString(VALID_NOT_BEFORE, certificate.getValidNotBefore()); + bundle.putString(VALID_NOT_AFTER, certificate.getValidNotAfter()); + X509Certificate x509Certificate = certificate.mX509Certificate; + if (x509Certificate != null) { + try { + bundle.putByteArray(X509_CERTIFICATE, x509Certificate.getEncoded()); + } catch (CertificateEncodingException ignored) { + } } - return bundle; } @@ -97,15 +117,27 @@ public class SslCertificate { * @return The SSL certificate stored in the bundle or null if fails */ public static SslCertificate restoreState(Bundle bundle) { - if (bundle != null) { - return new SslCertificate( - bundle.getString(ISSUED_TO), - bundle.getString(ISSUED_BY), - bundle.getString(VALID_NOT_BEFORE), - bundle.getString(VALID_NOT_AFTER)); + if (bundle == null) { + return null; } - - return null; + X509Certificate x509Certificate; + byte[] bytes = bundle.getByteArray(X509_CERTIFICATE); + if (bytes == null) { + x509Certificate = null; + } else { + try { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(bytes)); + x509Certificate = (X509Certificate) cert; + } catch (CertificateException e) { + x509Certificate = null; + } + } + return new SslCertificate(bundle.getString(ISSUED_TO), + bundle.getString(ISSUED_BY), + parseDate(bundle.getString(VALID_NOT_BEFORE)), + parseDate(bundle.getString(VALID_NOT_AFTER)), + x509Certificate); } /** @@ -121,7 +153,7 @@ public class SslCertificate { @Deprecated public SslCertificate( String issuedTo, String issuedBy, String validNotBefore, String validNotAfter) { - this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter)); + this(issuedTo, issuedBy, parseDate(validNotBefore), parseDate(validNotAfter), null); } /** @@ -135,10 +167,7 @@ public class SslCertificate { @Deprecated public SslCertificate( String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) { - mIssuedTo = new DName(issuedTo); - mIssuedBy = new DName(issuedBy); - mValidNotBefore = cloneDate(validNotBefore); - mValidNotAfter = cloneDate(validNotAfter); + this(issuedTo, issuedBy, validNotBefore, validNotAfter, null); } /** @@ -149,7 +178,19 @@ public class SslCertificate { this(certificate.getSubjectDN().getName(), certificate.getIssuerDN().getName(), certificate.getNotBefore(), - certificate.getNotAfter()); + certificate.getNotAfter(), + certificate); + } + + private SslCertificate( + String issuedTo, String issuedBy, + Date validNotBefore, Date validNotAfter, + X509Certificate x509Certificate) { + mIssuedTo = new DName(issuedTo); + mIssuedBy = new DName(issuedBy); + mValidNotBefore = cloneDate(validNotBefore); + mValidNotAfter = cloneDate(validNotAfter); + mX509Certificate = x509Certificate; } /** @@ -205,6 +246,54 @@ public class SslCertificate { } /** + * Convenience for UI presentation, not intended as public API. + */ + private static String getSerialNumber(X509Certificate x509Certificate) { + if (x509Certificate == null) { + return ""; + } + BigInteger serialNumber = x509Certificate.getSerialNumber(); + if (serialNumber == null) { + return ""; + } + return fingerprint(serialNumber.toByteArray()); + } + + /** + * Convenience for UI presentation, not intended as public API. + */ + private static String getDigest(X509Certificate x509Certificate, String algorithm) { + if (x509Certificate == null) { + return ""; + } + try { + byte[] bytes = x509Certificate.getEncoded(); + MessageDigest md = MessageDigest.getInstance(algorithm); + byte[] digest = md.digest(bytes); + return fingerprint(digest); + } catch (CertificateEncodingException ignored) { + return ""; + } catch (NoSuchAlgorithmException ignored) { + return ""; + } + } + + private static final String fingerprint(byte[] bytes) { + if (bytes == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[i]; + IntegralToString.appendByteAsHex(sb, b, true); + if (i+1 != bytes.length) { + sb.append(':'); + } + } + return sb.toString(); + } + + /** * @return A string representation of this certificate for debugging */ public String toString() { @@ -338,7 +427,6 @@ public class SslCertificate { * Inflates the SSL certificate view (helper method). * @return The resultant certificate view with issued-to, issued-by, * issued-on, expires-on, and possibly other fields set. - * If the input certificate is null, returns null. * * @hide Used by Browser and Settings */ @@ -352,33 +440,42 @@ public class SslCertificate { SslCertificate.DName issuedTo = getIssuedTo(); if (issuedTo != null) { ((TextView) certificateView.findViewById(com.android.internal.R.id.to_common)) - .setText(issuedTo.getCName()); + .setText(issuedTo.getCName()); ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org)) - .setText(issuedTo.getOName()); + .setText(issuedTo.getOName()); ((TextView) certificateView.findViewById(com.android.internal.R.id.to_org_unit)) - .setText(issuedTo.getUName()); + .setText(issuedTo.getUName()); } + // serial number: + ((TextView) certificateView.findViewById(com.android.internal.R.id.serial_number)) + .setText(getSerialNumber(mX509Certificate)); // issued by: SslCertificate.DName issuedBy = getIssuedBy(); if (issuedBy != null) { ((TextView) certificateView.findViewById(com.android.internal.R.id.by_common)) - .setText(issuedBy.getCName()); + .setText(issuedBy.getCName()); ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org)) - .setText(issuedBy.getOName()); + .setText(issuedBy.getOName()); ((TextView) certificateView.findViewById(com.android.internal.R.id.by_org_unit)) - .setText(issuedBy.getUName()); + .setText(issuedBy.getUName()); } // issued on: String issuedOn = formatCertificateDate(context, getValidNotBeforeDate()); ((TextView) certificateView.findViewById(com.android.internal.R.id.issued_on)) - .setText(issuedOn); + .setText(issuedOn); // expires on: String expiresOn = formatCertificateDate(context, getValidNotAfterDate()); ((TextView) certificateView.findViewById(com.android.internal.R.id.expires_on)) - .setText(expiresOn); + .setText(expiresOn); + + // fingerprints: + ((TextView) certificateView.findViewById(com.android.internal.R.id.sha256_fingerprint)) + .setText(getDigest(mX509Certificate, "SHA256")); + ((TextView) certificateView.findViewById(com.android.internal.R.id.sha1_fingerprint)) + .setText(getDigest(mX509Certificate, "SHA1")); return certificateView; } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 05e39ac..673b187 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -522,6 +522,9 @@ public class Process { argsForZygote.add("--runtime-init"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); + if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) { + argsForZygote.add("--enable-jni-logging"); + } if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { argsForZygote.add("--enable-safemode"); } diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 3bc1348..f799af3 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -275,6 +275,14 @@ public final class MediaStore { * @hide */ public static final String MEDIA_SCANNER_NEW_OBJECT_ID = "media_scanner_new_object_id"; + + /** + * Non-zero if the media file is drm-protected + * <P>Type: INTEGER (boolean)</P> + * @hide + */ + public static final String IS_DRM = "is_drm"; + } /** @@ -1124,19 +1132,19 @@ public final class MediaStore { public static final String IS_PODCAST = "is_podcast"; /** - * Non-zero id the audio file may be a ringtone + * Non-zero if the audio file may be a ringtone * <P>Type: INTEGER (boolean)</P> */ public static final String IS_RINGTONE = "is_ringtone"; /** - * Non-zero id the audio file may be an alarm + * Non-zero if the audio file may be an alarm * <P>Type: INTEGER (boolean)</P> */ public static final String IS_ALARM = "is_alarm"; /** - * Non-zero id the audio file may be a notification sound + * Non-zero if the audio file may be a notification sound * <P>Type: INTEGER (boolean)</P> */ public static final String IS_NOTIFICATION = "is_notification"; diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java index aaa7701..d0712d5 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -54,18 +54,6 @@ public class VoicemailContract { /** The authority used by the voicemail provider. */ public static final String AUTHORITY = "com.android.voicemail"; /** - * URI to insert/retrieve all voicemails. - * @deprecated - */ - public static final Uri CONTENT_URI = - Uri.parse("content://" + AUTHORITY + "/voicemail"); - /** - * URI to insert/retrieve voicemails by a given voicemail source. - * @deprecated - */ - public static final Uri CONTENT_URI_SOURCE = - Uri.parse("content://" + AUTHORITY + "/voicemail/source/"); - /** * Parameter key used in the URI to specify the voicemail source package name. * <p> This field must be set in all requests that originate from a voicemail source. */ @@ -82,9 +70,10 @@ public class VoicemailContract { public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE"; /** - * The mime type for a collection of voicemails. - * @deprecated */ - public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails"; + * Name of the source package field, which must be same across all voicemail related tables. + * @hide + */ + public static final String SOURCE_PACKAGE_FIELD = "source_package"; /** Defines fields exposed through the /voicemail path of this content provider. */ public static final class Voicemails implements BaseColumns { @@ -92,12 +81,9 @@ public class VoicemailContract { private Voicemails() { } - /** URI to insert/retrieve voicemails by a given voicemail source. */ + /** URI to insert/retrieve voicemails. */ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/voicemail"); - /** URI to insert/retrieve voicemails by a given voicemail source. */ - public static final Uri CONTENT_URI_SOURCE = - Uri.parse("content://" + AUTHORITY + "/voicemail/source/"); /** The mime type for a collection of voicemails. */ public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails"; @@ -139,7 +125,7 @@ public class VoicemailContract { * Package name of the source application that inserted the voicemail. * <P>Type: TEXT</P> */ - public static final String SOURCE_PACKAGE = "source_package"; + public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD; /** * Application-specific data available to the source application that * inserted the voicemail. This is typically used to store the source @@ -192,7 +178,7 @@ public class VoicemailContract { * The package name of the voicemail source. There can only be a one entry per source. * <P>Type: TEXT</P> */ - public static final String SOURCE_PACKAGE = "source_package"; + public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD; /** * The URI to call to invoke source specific voicemail settings screen. On a user request * to setup voicemail an intent with action VIEW with this URI will be fired by the system. diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index a3686b7..c7603ee 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -74,6 +74,12 @@ class AudioPlaybackHandler { removeMessages(token); if (token.getType() == MessageParams.TYPE_SYNTHESIS) { + AudioTrack current = ((SynthesisMessageParams) token).getAudioTrack(); + if (current != null) { + // Stop the current audio track if it's still playing. + // The audio track is thread safe in this regard. + current.stop(); + } mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY)); } else { final MessageParams current = getCurrentParams(); @@ -393,9 +399,10 @@ class AudioPlaybackHandler { try { if (audioTrack != null) { - audioTrack.flush(); - audioTrack.stop(); if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); + // The last call to AudioTrack.write( ) will return only after + // all data from the audioTrack has been sent to the mixer, so + // it's safe to release at this point. audioTrack.release(); } } finally { diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java index 9d84c3e..4a98336 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtype.java +++ b/core/java/android/view/inputmethod/InputMethodSubtype.java @@ -160,10 +160,10 @@ public final class InputMethodSubtype implements Parcelable { if (mSubtypeNameResId == 0) { return localeStr; } - final String subtypeName = context.getPackageManager().getText( - packageName, mSubtypeNameResId, appInfo).toString(); + final CharSequence subtypeName = context.getPackageManager().getText( + packageName, mSubtypeNameResId, appInfo); if (!TextUtils.isEmpty(subtypeName)) { - return String.format(subtypeName, localeStr); + return String.format(subtypeName.toString(), localeStr); } else { return localeStr; } diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index 79a5aff..5aa60f4 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -50,8 +50,10 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; +import java.util.HashSet; import java.util.Iterator; +import java.util.Map; +import java.util.Set; import org.apache.harmony.security.provider.cert.X509CertImpl; @@ -86,7 +88,8 @@ class BrowserFrame extends Handler { private boolean mIsMainFrame; // Attached Javascript interfaces - private Map<String, Object> mJSInterfaceMap; + private Map<String, Object> mJavaScriptObjects; + private Set<Object> mRemovedJavaScriptObjects; // Key store handler when Chromium HTTP stack is used. private KeyStoreHandler mKeyStoreHandler = null; @@ -229,10 +232,11 @@ class BrowserFrame extends Handler { } sConfigCallback.addHandler(this); - mJSInterfaceMap = javascriptInterfaces; - if (mJSInterfaceMap == null) { - mJSInterfaceMap = new HashMap<String, Object>(); + mJavaScriptObjects = javascriptInterfaces; + if (mJavaScriptObjects == null) { + mJavaScriptObjects = new HashMap<String, Object>(); } + mRemovedJavaScriptObjects = new HashSet<Object>(); mSettings = settings; mContext = context; @@ -241,7 +245,7 @@ class BrowserFrame extends Handler { mWebViewCore = w; mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy); - mJSInterfaceMap.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox); + mJavaScriptObjects.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox); AssetManager am = context.getAssets(); nativeCreateFrame(w, am, proxy.getBackForwardList()); @@ -598,15 +602,16 @@ class BrowserFrame extends Handler { * We should re-attach any attached js interfaces. */ private void windowObjectCleared(int nativeFramePointer) { - Iterator<String> iter = mJSInterfaceMap.keySet().iterator(); + Iterator<String> iter = mJavaScriptObjects.keySet().iterator(); while (iter.hasNext()) { String interfaceName = iter.next(); - Object object = mJSInterfaceMap.get(interfaceName); + Object object = mJavaScriptObjects.get(interfaceName); if (object != null) { nativeAddJavascriptInterface(nativeFramePointer, - mJSInterfaceMap.get(interfaceName), interfaceName); + mJavaScriptObjects.get(interfaceName), interfaceName); } } + mRemovedJavaScriptObjects.clear(); stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE); } @@ -632,12 +637,15 @@ class BrowserFrame extends Handler { assert obj != null; removeJavascriptInterface(interfaceName); - mJSInterfaceMap.put(interfaceName, obj); + mJavaScriptObjects.put(interfaceName, obj); } public void removeJavascriptInterface(String interfaceName) { - if (mJSInterfaceMap.containsKey(interfaceName)) { - mJSInterfaceMap.remove(interfaceName); + // We keep a reference to the removed object because the native side holds only a weak + // reference and we need to allow the object to continue to be used until the page has been + // navigated. + if (mJavaScriptObjects.containsKey(interfaceName)) { + mRemovedJavaScriptObjects.add(mJavaScriptObjects.remove(interfaceName)); } } diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index f7d55f6..0294e3f 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -119,6 +119,7 @@ class CallbackProxy extends Handler { private static final int NOTIFY_SEARCHBOX_LISTENERS = 139; private static final int AUTO_LOGIN = 140; private static final int CLIENT_CERT_REQUEST = 141; + private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK = 142; // Message triggered by the client to resume execution private static final int NOTIFY = 200; @@ -796,13 +797,14 @@ class CallbackProxy extends Handler { mWebChromeClient.setInstallableWebApp(); } break; - case NOTIFY_SEARCHBOX_LISTENERS: + case NOTIFY_SEARCHBOX_LISTENERS: { SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox(); @SuppressWarnings("unchecked") List<String> suggestions = (List<String>) msg.obj; searchBox.handleSuggestions(msg.getData().getString("query"), suggestions); break; + } case AUTO_LOGIN: { if (mWebViewClient != null) { String realm = msg.getData().getString("realm"); @@ -813,6 +815,12 @@ class CallbackProxy extends Handler { } break; } + case SEARCHBOX_IS_SUPPORTED_CALLBACK: { + SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox(); + Boolean supported = (Boolean) msg.obj; + searchBox.handleIsSupportedCallback(supported); + break; + } } } @@ -1627,4 +1635,10 @@ class CallbackProxy extends Handler { sendMessage(msg); } + + void onIsSupportedCallback(boolean isSupported) { + Message msg = obtainMessage(SEARCHBOX_IS_SUPPORTED_CALLBACK); + msg.obj = new Boolean(isSupported); + sendMessage(msg); + } } diff --git a/core/java/android/webkit/SearchBox.java b/core/java/android/webkit/SearchBox.java index 57c7b03..5075302 100644 --- a/core/java/android/webkit/SearchBox.java +++ b/core/java/android/webkit/SearchBox.java @@ -83,10 +83,19 @@ public interface SearchBox { void removeSearchBoxListener(SearchBoxListener l); /** + * Indicates if the searchbox API is supported in the current page. + */ + void isSupported(IsSupportedCallback callback); + + /** * Listeners (if any) will be called on the thread that created the * webview. */ interface SearchBoxListener { void onSuggestionsReceived(String query, List<String> suggestions); } + + interface IsSupportedCallback { + void searchBoxIsSupported(boolean supported); + } } diff --git a/core/java/android/webkit/SearchBoxImpl.java b/core/java/android/webkit/SearchBoxImpl.java index 480f5d7..61fb2ce 100644 --- a/core/java/android/webkit/SearchBoxImpl.java +++ b/core/java/android/webkit/SearchBoxImpl.java @@ -92,9 +92,19 @@ final class SearchBoxImpl implements SearchBox { = "if (window.chrome && window.chrome.searchBox &&" + " window.chrome.searchBox.on%1$s) { window.chrome.searchBox.on%1$s(); }"; + private static final String IS_SUPPORTED_SCRIPT + = "if (window.searchBoxJavaBridge_) {" + + " if (window.chrome && window.chrome.searchBox && " + + " window.chrome.searchBox.onsubmit) {" + + " window.searchBoxJavaBridge_.isSupportedCallback(true);" + + " } else {" + + " window.searchBoxJavaBridge_.isSupportedCallback(false);" + + " }}"; + private final List<SearchBoxListener> mListeners; private final WebViewCore mWebViewCore; private final CallbackProxy mCallbackProxy; + private IsSupportedCallback mSupportedCallback; SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) { mListeners = new ArrayList<SearchBoxListener>(); @@ -173,6 +183,25 @@ final class SearchBoxImpl implements SearchBox { } } + @Override + public void isSupported(IsSupportedCallback callback) { + mSupportedCallback = callback; + dispatchJs(IS_SUPPORTED_SCRIPT); + } + + // Called by Javascript through the Java bridge. + public void isSupportedCallback(boolean isSupported) { + mCallbackProxy.onIsSupportedCallback(isSupported); + } + + public void handleIsSupportedCallback(boolean isSupported) { + IsSupportedCallback callback = mSupportedCallback; + mSupportedCallback = null; + if (callback != null) { + callback.searchBoxIsSupported(isSupported); + } + } + // This is used as a hackish alternative to javascript escaping. // There appears to be no such functionality in the core framework. private String jsonSerialize(String query) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9f632d1..7ba86a5 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1971,9 +1971,14 @@ public class WebView extends AbsoluteLayout } /** - * Load the given data into the WebView using a 'data' scheme URL. Content - * loaded in this way does not have the ability to load content from the - * network. + * Load the given data into the WebView using a 'data' scheme URL. + * <p> + * Note that JavaScript's same origin policy means that script running in a + * page loaded using this method will be unable to access content loaded + * using any scheme other than 'data', including 'http(s)'. To avoid this + * restriction, use {@link + * #loadDataWithBaseURL(String,String,String,String,String) + * loadDataWithBaseURL()} with an appropriate base URL. * <p> * If the value of the encoding parameter is 'base64', then the data must * be encoded as base64. Otherwise, the data must use ASCII encoding for @@ -2000,21 +2005,26 @@ public class WebView extends AbsoluteLayout } /** - * Load the given data into the WebView, use the provided URL as the base - * URL for the content. The base URL is the URL that represents the page - * that is loaded through this interface. As such, it is used to resolve any - * relative URLs. The historyUrl is used for the history entry. + * Load the given data into the WebView, using baseUrl as the base URL for + * the content. The base URL is used both to resolve relative URLs and when + * applying JavaScript's same origin policy. The historyUrl is used for the + * history entry. * <p> * Note that content specified in this way can access local device files * (via 'file' scheme URLs) only if baseUrl specifies a scheme other than * 'http', 'https', 'ftp', 'ftps', 'about' or 'javascript'. - * @param baseUrl Url to resolve relative paths with, if null defaults to - * "about:blank" + * <p> + * If the base URL uses the data scheme, this method is equivalent to + * calling {@link #loadData(String,String,String) loadData()} and the + * historyUrl is ignored. + * @param baseUrl URL to use as the page's base URL. If null defaults to + * 'about:blank' * @param data A String of data in the given encoding. - * @param mimeType The MIMEType of the data. i.e. text/html. If null, - * defaults to "text/html" - * @param encoding The encoding of the data. i.e. utf-8, us-ascii - * @param historyUrl URL to use as the history entry. Can be null. + * @param mimeType The MIMEType of the data, e.g. 'text/html'. If null, + * defaults to 'text/html'. + * @param encoding The encoding of the data. + * @param historyUrl URL to use as the history entry, if null defaults to + * 'about:blank'. */ public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) { diff --git a/core/java/android/webkit/WebViewFragment.java b/core/java/android/webkit/WebViewFragment.java index 466f174..852878b 100644 --- a/core/java/android/webkit/WebViewFragment.java +++ b/core/java/android/webkit/WebViewFragment.java @@ -30,6 +30,7 @@ import android.webkit.WebView; */ public class WebViewFragment extends Fragment { private WebView mWebView; + private boolean mIsWebViewAvailable; public WebViewFragment() { } @@ -40,7 +41,11 @@ public class WebViewFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (mWebView != null) { + mWebView.destroy(); + } mWebView = new WebView(getActivity()); + mIsWebViewAvailable = true; return mWebView; } @@ -63,19 +68,31 @@ public class WebViewFragment extends Fragment { } /** - * Called when the view has been detached from the fragment. Destroys the WebView. + * Called when the WebView has been detached from the fragment. + * The WebView is no longer available after this time. */ @Override public void onDestroyView() { - mWebView.destroy(); - mWebView = null; + mIsWebViewAvailable = false; super.onDestroyView(); } /** + * Called when the fragment is no longer in use. Destroys the internal state of the WebView. + */ + @Override + public void onDestroy() { + if (mWebView != null) { + mWebView.destroy(); + mWebView = null; + } + super.onDestroy(); + } + + /** * Gets the WebView. */ public WebView getWebView() { - return mWebView; + return mIsWebViewAvailable ? mWebView : null; } } diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 7d43e94..252fc8f 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -1111,6 +1111,12 @@ class ZoomManager { mTextWrapScale = Math.max(mTextWrapScale, overviewScale); } reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale); + } else { + // In case of restored scale, treat defaultScale as overview since + // it usually means the previous scale is not saved. + if (scale == mDefaultScale && settings.getLoadWithOverviewMode()) { + scale = overviewScale; + } } mInitialZoomOverview = settings.getLoadWithOverviewMode() && !exceedsMinScaleIncrement(scale, overviewScale); diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index fc8bce8..427fd3e 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -301,49 +301,55 @@ public class LinearLayout extends ViewGroup { void drawDividersVertical(Canvas canvas) { final int count = getVirtualChildCount(); - int top = getPaddingTop(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null) { - top += measureNullChild(i); - } else if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int top = child.getTop() - lp.topMargin; drawHorizontalDivider(canvas, top); - top += mDividerHeight; } - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - top += lp.topMargin + child.getHeight() + lp.bottomMargin; } } if (hasDividerBeforeChildAt(count)) { - drawHorizontalDivider(canvas, top); + final View child = getVirtualChildAt(count - 1); + int bottom = 0; + if (child == null) { + bottom = getHeight() - getPaddingBottom() - mDividerHeight; + } else { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + bottom = child.getBottom() + lp.bottomMargin; + } + drawHorizontalDivider(canvas, bottom); } } void drawDividersHorizontal(Canvas canvas) { final int count = getVirtualChildCount(); - int left = getPaddingLeft(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null) { - left += measureNullChild(i); - } else if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int left = child.getLeft() - lp.leftMargin; drawVerticalDivider(canvas, left); - left += mDividerWidth; } - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - left += lp.leftMargin + child.getWidth() + lp.rightMargin; } } if (hasDividerBeforeChildAt(count)) { - drawVerticalDivider(canvas, left); + final View child = getVirtualChildAt(count - 1); + int right = 0; + if (child == null) { + right = getWidth() - getPaddingRight() - mDividerWidth; + } else { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + right = child.getRight() + lp.rightMargin; + } + drawVerticalDivider(canvas, right); } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index c91f1a6..772e8e9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8901,7 +8901,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme); boolean allowText = getContext().getResources().getBoolean( - com.android.internal.R.bool.allow_action_menu_item_text_with_icon); + com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon); mode.setTitle(allowText ? mContext.getString(com.android.internal.R.string.textSelectionCABTitle) : null); diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.aidl b/core/java/com/android/internal/net/LegacyVpnInfo.aidl new file mode 100644 index 0000000..0ca2627 --- /dev/null +++ b/core/java/com/android/internal/net/LegacyVpnInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.net; + +parcelable LegacyVpnInfo; diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java new file mode 100644 index 0000000..b620aba --- /dev/null +++ b/core/java/com/android/internal/net/LegacyVpnInfo.java @@ -0,0 +1,69 @@ +/* + * 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.net; + +import android.app.PendingIntent; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A simple container used to carry information of the ongoing legacy VPN. + * Internal use only. + * + * @hide + */ +public class LegacyVpnInfo implements Parcelable { + public static final int STATE_DISCONNECTED = 0; + public static final int STATE_INITIALIZING = 1; + public static final int STATE_CONNECTING = 2; + public static final int STATE_CONNECTED = 3; + public static final int STATE_TIMEOUT = 4; + public static final int STATE_FAILED = 5; + + public String key; + public int state = -1; + public PendingIntent intent; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeString(key); + out.writeInt(state); + out.writeParcelable(intent, flags); + } + + public static final Parcelable.Creator<LegacyVpnInfo> CREATOR = + new Parcelable.Creator<LegacyVpnInfo>() { + @Override + public LegacyVpnInfo createFromParcel(Parcel in) { + LegacyVpnInfo info = new LegacyVpnInfo(); + info.key = in.readString(); + info.state = in.readInt(); + info.intent = in.readParcelable(null); + return info; + } + + @Override + public LegacyVpnInfo[] newArray(int size) { + return new LegacyVpnInfo[size]; + } + }; +} diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java index 003c244..d36be10 100644 --- a/core/java/com/android/internal/net/VpnConfig.java +++ b/core/java/com/android/internal/net/VpnConfig.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.Intent; import android.os.Parcel; import android.os.Parcelable; -import android.os.SystemClock; import java.util.List; @@ -43,14 +42,14 @@ public class VpnConfig implements Parcelable { return intent; } - public static PendingIntent getIntentForNotification(Context context, VpnConfig config) { - config.startTime = SystemClock.elapsedRealtime(); + public static PendingIntent getIntentForStatusPanel(Context context, VpnConfig config) { Intent intent = new Intent(); intent.setClassName("com.android.vpndialogs", "com.android.vpndialogs.ManageDialog"); intent.putExtra("config", config); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + return PendingIntent.getActivity(context, 0, intent, (config == null) ? + PendingIntent.FLAG_NO_CREATE : PendingIntent.FLAG_CANCEL_CURRENT); } public String packagz; diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index b872e22..7cb002c 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -328,8 +328,8 @@ class ZygoteConnection { boolean peerWait; /** - * From --enable-debugger, --enable-checkjni, --enable-assert, and - * --enable-safemode + * From --enable-debugger, --enable-checkjni, --enable-assert, + * --enable-safemode, and --enable-jni-logging. */ int debugFlags; @@ -408,6 +408,8 @@ class ZygoteConnection { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } else if (arg.equals("--enable-checkjni")) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; + } else if (arg.equals("--enable-jni-logging")) { + debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } else if (arg.equals("--peer-wait")) { diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java index 479788d..3b497e4 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java @@ -17,6 +17,7 @@ package com.android.internal.view.menu; import android.content.Context; +import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.AttributeSet; @@ -38,17 +39,24 @@ public class ActionMenuItemView extends LinearLayout private ImageButton mImageButton; private Button mTextButton; + private boolean mAllowTextWithIcon; + private boolean mShowTextAllCaps; + private boolean mExpandedFormat; public ActionMenuItemView(Context context) { this(context, null); } public ActionMenuItemView(Context context, AttributeSet attrs) { - super(context, attrs); + this(context, attrs, 0); } public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + final Resources res = context.getResources(); + mAllowTextWithIcon = res.getBoolean( + com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon); + mShowTextAllCaps = res.getBoolean(com.android.internal.R.bool.config_actionMenuItemAllCaps); } @Override @@ -104,9 +112,20 @@ public class ActionMenuItemView extends LinearLayout // TODO Support checkable action items } + public void setExpandedFormat(boolean expandedFormat) { + if (mExpandedFormat != expandedFormat) { + mExpandedFormat = expandedFormat; + if (mItemData != null) { + mItemData.actionFormatChanged(); + } + } + } + private void updateTextButtonVisibility() { boolean visible = !TextUtils.isEmpty(mTextButton.getText()); - visible = visible && (mImageButton.getDrawable() == null || mItemData.showsTextAsAction()); + visible &= mImageButton.getDrawable() == null || + (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat)); + mTextButton.setVisibility(visible ? VISIBLE : GONE); } @@ -135,7 +154,12 @@ public class ActionMenuItemView extends LinearLayout // populate accessibility description with title setContentDescription(title); - mTextButton.setText(mTitle); + if (mShowTextAllCaps && title != null) { + mTextButton.setText(title.toString().toUpperCase( + getContext().getResources().getConfiguration().locale)); + } else { + mTextButton.setText(mTitle); + } updateTextButtonVisibility(); } diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 2fec9cd..b86eb13 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -19,8 +19,8 @@ package com.android.internal.view.menu; import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView; import android.content.Context; -import android.content.res.Configuration; import android.content.res.Resources; +import android.util.Log; import android.util.SparseBooleanArray; import android.view.MenuItem; import android.view.SoundEffectConstants; @@ -48,6 +48,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter { private boolean mStrictWidthLimit; private boolean mWidthLimitSet; + private int mMinCellSize; + // Group IDs that have been added as actions - used temporarily, allocated here for reuse. private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray(); @@ -96,6 +98,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter { mActionItemWidthLimit = width; + mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density); + // Drop a scrap view as it may no longer reflect the proper context/config. mScrapActionButtonView = null; } @@ -126,16 +130,30 @@ public class ActionMenuPresenter extends BaseMenuPresenter { @Override public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { View actionView = item.getActionView(); - actionView = actionView != null && !item.hasCollapsibleActionView() ? - actionView : super.getItemView(item, convertView, parent); + if (actionView == null || item.hasCollapsibleActionView()) { + if (!(convertView instanceof ActionMenuItemView)) { + convertView = null; + } + actionView = super.getItemView(item, convertView, parent); + } actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); + + final ActionMenuView menuParent = (ActionMenuView) parent; + final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); + if (!menuParent.checkLayoutParams(lp)) { + actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); + } return actionView; } @Override public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { itemView.initialize(item, 0); - ((ActionMenuItemView) itemView).setItemInvoker((ActionMenuView) mMenuView); + + final ActionMenuView menuView = (ActionMenuView) mMenuView; + ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; + actionItemView.setItemInvoker(menuView); + if (false) actionItemView.setExpandedFormat(menuView.isExpandedFormat()); } @Override @@ -150,15 +168,14 @@ public class ActionMenuPresenter extends BaseMenuPresenter { if (mReserveOverflow && mMenu.getNonActionItems().size() > 0) { if (mOverflowButton == null) { mOverflowButton = new OverflowMenuButton(mContext); - mOverflowButton.setLayoutParams( - ((ActionMenuView) mMenuView).generateOverflowButtonLayoutParams()); } ViewGroup parent = (ViewGroup) mOverflowButton.getParent(); if (parent != mMenuView) { if (parent != null) { parent.removeView(mOverflowButton); } - ((ViewGroup) mMenuView).addView(mOverflowButton); + ActionMenuView menuView = (ActionMenuView) mMenuView; + menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams()); } } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) { ((ViewGroup) mMenuView).removeView(mOverflowButton); @@ -313,19 +330,29 @@ public class ActionMenuPresenter extends BaseMenuPresenter { final SparseBooleanArray seenGroups = mActionButtonGroups; seenGroups.clear(); + int cellSize = 0; + int cellsRemaining = 0; + if (mStrictWidthLimit) { + cellsRemaining = widthLimit / mMinCellSize; + final int cellSizeRemaining = widthLimit % mMinCellSize; + cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining; + } + // Flag as many more requested items as will fit. for (int i = 0; i < itemsSize; i++) { MenuItemImpl item = visibleItems.get(i); if (item.requiresActionButton()) { - View v = item.getActionView(); - if (v == null || item.hasCollapsibleActionView()) { - v = getItemView(item, mScrapActionButtonView, parent); - if (mScrapActionButtonView == null) { - mScrapActionButtonView = v; - } + View v = getItemView(item, mScrapActionButtonView, parent); + if (mScrapActionButtonView == null) { + mScrapActionButtonView = v; + } + if (mStrictWidthLimit) { + cellsRemaining -= ActionMenuView.measureChildForCells(v, + cellSize, cellsRemaining, querySpec, 0); + } else { + v.measure(querySpec, querySpec); } - v.measure(querySpec, querySpec); final int measuredWidth = v.getMeasuredWidth(); widthLimit -= measuredWidth; if (firstActionWidth == 0) { @@ -341,18 +368,25 @@ public class ActionMenuPresenter extends BaseMenuPresenter { // can break the max actions rule, but not the width limit. final int groupId = item.getGroupId(); final boolean inGroup = seenGroups.get(groupId); - boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0; + boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 && + (!mStrictWidthLimit || cellsRemaining > 0); maxActions--; if (isAction) { - View v = item.getActionView(); - if (v == null || item.hasCollapsibleActionView()) { - v = getItemView(item, mScrapActionButtonView, parent); - if (mScrapActionButtonView == null) { - mScrapActionButtonView = v; + View v = getItemView(item, mScrapActionButtonView, parent); + if (mScrapActionButtonView == null) { + mScrapActionButtonView = v; + } + if (mStrictWidthLimit) { + final int cells = ActionMenuView.measureChildForCells(v, + cellSize, cellsRemaining, querySpec, 0); + cellsRemaining -= cells; + if (cells == 0) { + isAction = false; } + } else { + v.measure(querySpec, querySpec); } - v.measure(querySpec, querySpec); final int measuredWidth = v.getMeasuredWidth(); widthLimit -= measuredWidth; if (firstActionWidth == 0) { @@ -360,10 +394,10 @@ public class ActionMenuPresenter extends BaseMenuPresenter { } if (mStrictWidthLimit) { - isAction = widthLimit >= 0; + isAction &= widthLimit >= 0; } else { // Did this push the entire first item past the limit? - isAction = widthLimit + firstActionWidth > 0; + isAction &= widthLimit + firstActionWidth > 0; } } @@ -414,7 +448,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter { } public boolean needsDividerBefore() { - return true; + return false; } public boolean needsDividerAfter() { diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index 7b4f216..cfe9e59 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -30,12 +30,16 @@ import android.widget.LinearLayout; public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView { private static final String TAG = "ActionMenuView"; + static final int MIN_CELL_SIZE = 56; // dips + private MenuBuilder mMenu; private boolean mReserveOverflow; private ActionMenuPresenter mPresenter; private boolean mUpdateContentsBeforeMeasure; private boolean mFormatItems; + private int mMinCellSize; + private int mMeasuredExtraWidth; public ActionMenuView(Context context) { this(context, null); @@ -44,12 +48,17 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo public ActionMenuView(Context context, AttributeSet attrs) { super(context, attrs); setBaselineAligned(false); + mMinCellSize = (int) (MIN_CELL_SIZE * context.getResources().getDisplayMetrics().density); } public void setPresenter(ActionMenuPresenter presenter) { mPresenter = presenter; } + public boolean isExpandedFormat() { + return mFormatItems; + } + @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -70,13 +79,196 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // If we've been given an exact size to match, apply special formatting during layout. + mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; if (mUpdateContentsBeforeMeasure && mMenu != null) { mMenu.onItemsChanged(true); mUpdateContentsBeforeMeasure = false; } - // If we've been given an exact size to match, apply special formatting during layout. - mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (mFormatItems) { + onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) { + // We already know the width mode is EXACTLY if we're here. + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + final int widthPadding = getPaddingLeft() + getPaddingRight(); + final int heightPadding = getPaddingTop() + getPaddingBottom(); + + widthSize -= widthPadding; + + // Divide the view into cells. + final int cellCount = widthSize / mMinCellSize; + final int cellSizeRemaining = widthSize % mMinCellSize; + final int cellSize = mMinCellSize + cellSizeRemaining / cellCount; + + int cellsRemaining = cellCount; + int maxChildHeight = 0; + int maxCellsUsed = 0; + int multiCellItemCount = 0; + + if (mReserveOverflow) cellsRemaining--; + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + lp.expanded = false; + lp.extraPixels = 0; + lp.cellsUsed = 0; + lp.multiCell = false; + + // Overflow always gets 1 cell. No more, no less. + final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining; + + final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, + heightMeasureSpec, heightPadding); + + maxCellsUsed = Math.max(maxCellsUsed, cellsUsed); + if (lp.multiCell) multiCellItemCount++; + + cellsRemaining -= cellsUsed; + maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); + } + + // Divide space for remaining cells if we have items that can expand. + // Try distributing whole leftover cells to smaller items first. + + boolean needsExpansion = false; + long smallestMultiCellItemsAt = 0; + while (multiCellItemCount > 0 && cellsRemaining > 0) { + int minCells = Integer.MAX_VALUE; + long minCellsAt = 0; // Bit locations are indices of relevant child views + int minCellsItemCount = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + // Don't try to expand items that shouldn't. + if (!lp.multiCell) continue; + + // Mark indices of children that can receive an extra cell. + if (lp.cellsUsed < minCells) { + minCells = lp.cellsUsed; + minCellsAt = 1 << i; + minCellsItemCount = 1; + } else if (lp.cellsUsed == minCells) { + minCellsAt |= 1 << i; + minCellsItemCount++; + } + } + + if (minCellsItemCount < cellsRemaining) break; // Couldn't expand anything evenly. Stop. + + // Items that get expanded will always be in the set of smallest items when we're done. + smallestMultiCellItemsAt |= minCellsAt; + + for (int i = 0; i < childCount; i++) { + if ((minCellsAt & (1 << i)) == 0) continue; + + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + lp.cellsUsed++; + lp.expanded = true; + cellsRemaining--; + } + + needsExpansion = true; + } + + // Divide any space left that wouldn't divide along cell boundaries + // evenly among the smallest multi-cell (expandable) items. + + if (cellsRemaining > 0 && smallestMultiCellItemsAt != 0) { + final int expandCount = Long.bitCount(smallestMultiCellItemsAt); + final int extraPixels = cellsRemaining * cellSize / expandCount; + + for (int i = 0; i < childCount; i++) { + if ((smallestMultiCellItemsAt & (1 << i)) == 0) continue; + + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + lp.extraPixels = extraPixels; + lp.expanded = true; + } + + needsExpansion = true; + cellsRemaining = 0; + } + + // Remeasure any items that have had extra space allocated to them. + if (needsExpansion) { + int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (!lp.expanded) continue; + + final int width = lp.cellsUsed * cellSize + lp.extraPixels; + child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec); + } + } + + if (heightMode != MeasureSpec.EXACTLY) { + heightSize = maxChildHeight; + } + + setMeasuredDimension(widthSize, heightSize); + mMeasuredExtraWidth = cellsRemaining * cellSize; + } + + /** + * Measure a child view to fit within cell-based formatting. The child's width + * will be measured to a whole multiple of cellSize. + * + * <p>Sets the multiCell and cellsUsed fields of LayoutParams. + * + * @param child Child to measure + * @param cellSize Size of one cell + * @param cellsRemaining Number of cells remaining that this view can expand to fill + * @param parentHeightMeasureSpec MeasureSpec used by the parent view + * @param parentHeightPadding Padding present in the parent view + * @return Number of cells this child was measured to occupy + */ + static int measureChildForCells(View child, int cellSize, int cellsRemaining, + int parentHeightMeasureSpec, int parentHeightPadding) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? + (ActionMenuItemView) child : null; + + final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - + parentHeightPadding; + final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); + final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); + + int cellsUsed = cellsRemaining > 0 ? 1 : 0; + final boolean multiCell = !lp.isOverflowButton && + (itemView == null || itemView.hasText()); + + lp.multiCell = multiCell; + + if (multiCell && cellsRemaining > 0) { + final int childWidthSpec = MeasureSpec.makeMeasureSpec( + cellSize * cellsRemaining, MeasureSpec.AT_MOST); + child.measure(childWidthSpec, childHeightSpec); + + final int measuredWidth = child.getMeasuredWidth(); + cellsUsed = measuredWidth / cellSize; + if (measuredWidth % cellSize != 0) cellsUsed++; + } + lp.cellsUsed = cellsUsed; + final int targetWidth = cellsUsed * cellSize; + child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), + childHeightSpec); + return cellsUsed; } @Override @@ -93,6 +285,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo int nonOverflowWidth = 0; int nonOverflowCount = 0; int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); + boolean hasOverflow = false; for (int i = 0; i < childCount; i++) { final View v = getChildAt(i); if (v.getVisibility() == GONE) { @@ -107,15 +300,18 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } int height = v.getMeasuredHeight(); - int r = getPaddingRight(); + int r = getWidth() - getPaddingRight(); int l = r - overflowWidth; int t = midVertical - (height / 2); int b = t + height; v.layout(l, t, r, b); widthRemaining -= overflowWidth; + hasOverflow = true; } else { - nonOverflowWidth += v.getMeasuredWidth() + p.leftMargin + p.rightMargin; + final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin; + nonOverflowWidth += size; + widthRemaining -= size; if (hasDividerBeforeChildAt(i)) { nonOverflowWidth += dividerWidth; } @@ -123,10 +319,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } } - // Fill action items from the left. Overflow will always pin to the right edge. - if (nonOverflowWidth <= widthRemaining - overflowWidth) { - widthRemaining -= overflowWidth; - } + final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1); + final int spacerSize = spacerCount > 0 ? widthRemaining / spacerCount : 0; int startLeft = getPaddingLeft(); for (int i = 0; i < childCount; i++) { @@ -141,7 +335,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo int height = v.getMeasuredHeight(); int t = midVertical - (height / 2); v.layout(startLeft, t, startLeft + width, t + height); - startLeft += width + lp.rightMargin; + startLeft += width + lp.rightMargin + spacerSize; } } @@ -168,6 +362,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { if (p instanceof LayoutParams) { LayoutParams result = new LayoutParams((LayoutParams) p); @@ -181,7 +380,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; + return p != null && p instanceof LayoutParams; } public LayoutParams generateOverflowButtonLayoutParams() { @@ -224,6 +423,13 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo public static class LayoutParams extends LinearLayout.LayoutParams { @ViewDebug.ExportedProperty(category = "layout") public boolean isOverflowButton; + @ViewDebug.ExportedProperty(category = "layout") + public int cellsUsed; + @ViewDebug.ExportedProperty(category = "layout") + public boolean multiCell; + @ViewDebug.ExportedProperty(category = "layout") + public int extraPixels; + public boolean expanded; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 7b1dfb0..20b7d80 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -506,6 +506,10 @@ public final class MenuItemImpl implements MenuItem { return mMenuInfo; } + public void actionFormatChanged() { + mMenu.onItemActionRequestChanged(this); + } + /** * @return Whether the menu should show icons for menu items. */ @@ -534,9 +538,7 @@ public final class MenuItemImpl implements MenuItem { } public boolean showsTextAsAction() { - return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT && - mMenu.getContext().getResources().getBoolean( - com.android.internal.R.bool.allow_action_menu_item_text_with_icon); + return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT; } public void setShowAsAction(int actionEnum) { diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java index 953328c..9fef2a9 100644 --- a/core/java/com/android/internal/widget/ActionBarContainer.java +++ b/core/java/com/android/internal/widget/ActionBarContainer.java @@ -19,6 +19,8 @@ package com.android.internal.widget; import android.app.ActionBar; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.ActionMode; import android.view.MotionEvent; @@ -35,6 +37,12 @@ public class ActionBarContainer extends FrameLayout { private View mTabContainer; private ActionBarView mActionBarView; + private Drawable mBackground; + private Drawable mStackedBackground; + private Drawable mSplitBackground; + private boolean mIsSplit; + private boolean mIsStacked; + public ActionBarContainer(Context context) { this(context, null); } @@ -42,10 +50,23 @@ public class ActionBarContainer extends FrameLayout { public ActionBarContainer(Context context, AttributeSet attrs) { super(context, attrs); + setBackgroundDrawable(null); + TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ActionBar); - setBackgroundDrawable(a.getDrawable(com.android.internal.R.styleable.ActionBar_background)); + mBackground = a.getDrawable(com.android.internal.R.styleable.ActionBar_background); + mStackedBackground = a.getDrawable( + com.android.internal.R.styleable.ActionBar_backgroundStacked); + + if (getId() == com.android.internal.R.id.split_action_bar) { + mIsSplit = true; + mSplitBackground = a.getDrawable( + com.android.internal.R.styleable.ActionBar_backgroundSplit); + } a.recycle(); + + setWillNotDraw(mIsSplit ? mSplitBackground == null : + mBackground == null && mStackedBackground == null); } @Override @@ -96,6 +117,24 @@ public class ActionBarContainer extends FrameLayout { } @Override + public void onDraw(Canvas canvas) { + if (getWidth() == 0 || getHeight() == 0) { + return; + } + + if (mIsSplit) { + if (mSplitBackground != null) mSplitBackground.draw(canvas); + } else { + if (mBackground != null) { + mBackground.draw(canvas); + } + if (mStackedBackground != null && mIsStacked) { + mStackedBackground.draw(canvas); + } + } + } + + @Override public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) { // No starting an action mode for an action bar child! (Where would it go?) return null; @@ -125,6 +164,9 @@ public class ActionBarContainer extends FrameLayout { @Override public void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); + + final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE; + if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { final int containerHeight = getMeasuredHeight(); final int tabHeight = mTabContainer.getMeasuredHeight(); @@ -146,5 +188,28 @@ public class ActionBarContainer extends FrameLayout { mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight); } } + + boolean needsInvalidate = false; + if (mIsSplit) { + if (mSplitBackground != null) { + mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + needsInvalidate = true; + } + } else { + if (mBackground != null) { + mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(), + mActionBarView.getRight(), mActionBarView.getBottom()); + needsInvalidate = true; + } + if ((mIsStacked = hasTabs && mStackedBackground != null)) { + mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(), + mTabContainer.getRight(), mTabContainer.getBottom()); + needsInvalidate = true; + } + } + + if (needsInvalidate) { + invalidate(); + } } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1a32060..49eaf19 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1418,7 +1418,6 @@ android:label="@string/android_system_label" android:allowClearUserData="false" android:backupAgent="com.android.server.SystemBackupAgent" - android:fullBackupAgent="com.android.server.SystemBackupAgent" android:killAfterRestore="false" android:icon="@drawable/ic_launcher_android"> <activity android:name="com.android.internal.app.ChooserActivity" diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..3ea6c44 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_bottom_solid_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..6c6fcd2 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_bottom_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..854631e --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_bottom_solid_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..aef6142d --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..d8b5edc --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..660a234 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_solid_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..9756cf5 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_solid_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png Binary files differnew file mode 100644 index 0000000..80213d5 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_solid_shadow_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..6de2bf2 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_stacked_solid_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..c23e473 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_stacked_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..343d7c6 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_stacked_solid_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..3de1174 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..da8b042 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..1957c32 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..0f1ce73 --- /dev/null +++ b/core/res/res/drawable-hdpi/ab_transparent_light_holo.9.png diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png Binary files differindex 7855cda..897a1c1 100644 --- a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png Binary files differindex c062773..0c89f71 100644 --- a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_copy.png b/core/res/res/drawable-hdpi/ic_menu_copy.png Binary files differnew file mode 100644 index 0000000..5dcc3a3 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_menu_copy.png diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png Binary files differindex 852f146..d1e1337 100644 --- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png Binary files differindex ad09b37..5d02660 100644 --- a/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut.png b/core/res/res/drawable-hdpi/ic_menu_cut.png Binary files differnew file mode 100644 index 0000000..03fac98 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_menu_cut.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png Binary files differindex 7716a94..bd28a85 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png Binary files differindex bea6db1..037c362 100644 --- a/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png Binary files differindex b888202..b981a4d 100644 --- a/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png Binary files differindex b888202..efee6df 100644 --- a/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_find_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png Binary files differnew file mode 100644 index 0000000..33bb5e76 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow.png diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differindex 8563c1a..1e69eac 100644 --- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differindex 1cd2384..2f6accc 100644 --- a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_paste.png b/core/res/res/drawable-hdpi/ic_menu_paste.png Binary files differnew file mode 100644 index 0000000..c24fd86 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_menu_paste.png diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png Binary files differindex 5579443..e9514b8 100644 --- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png Binary files differindex 6674914..b02aa09 100644 --- a/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png Binary files differindex 2837615..db011be 100644 --- a/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png Binary files differindex 2837615..d9a9a73 100644 --- a/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_menu_share_holo_light.png diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..3807a48 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_bottom_solid_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..9994438 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_bottom_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..5648403 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_bottom_solid_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..261365d --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..95df5fc --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..4a6c3bc --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_solid_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..93a0c3e --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_solid_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png Binary files differnew file mode 100644 index 0000000..f3abd07 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_solid_shadow_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..e1d8f67 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_stacked_solid_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..9d7e953 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_stacked_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..711e0fd --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_stacked_solid_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..9649a2d --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..376e4ef --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..99c8fd3 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..a86ec34 --- /dev/null +++ b/core/res/res/drawable-mdpi/ab_transparent_light_holo.9.png diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png Binary files differindex ae3e6bf..df2d3d1 100644 --- a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png Binary files differindex c61e3fa..b2aa9c2 100644 --- a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_copy.png b/core/res/res/drawable-mdpi/ic_menu_copy.png Binary files differnew file mode 100644 index 0000000..eee5540 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_menu_copy.png diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png Binary files differindex 35c3318..cb19fea 100644 --- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png Binary files differindex 3b179d8..e353d46 100644 --- a/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut.png b/core/res/res/drawable-mdpi/ic_menu_cut.png Binary files differnew file mode 100644 index 0000000..865d1e0 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_menu_cut.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png Binary files differindex dfe8b4a..66a750d 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png Binary files differindex 748dc9b..e7e8c54 100644 --- a/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png Binary files differindex 82dcba7..45f8fd3 100644 --- a/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png Binary files differindex 82dcba7..9033f1e 100644 --- a/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_find_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png Binary files differnew file mode 100644 index 0000000..e478922 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png Binary files differindex c369e6f..48d6c78 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png Binary files differindex a4df2bf..50ff8fc 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_focused_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differindex a7389c9..135ca6e 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differindex 87e41ac..ccbf143 100644 --- a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_paste.png b/core/res/res/drawable-mdpi/ic_menu_paste.png Binary files differnew file mode 100644 index 0000000..8c9916c --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_menu_paste.png diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png Binary files differindex caec299..23f3a32 100644 --- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png Binary files differindex 434f5d1..c9d571c 100644 --- a/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png Binary files differindex d89ca5f..306cac8 100755..100644 --- a/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png Binary files differindex d89ca5f..cc081ad 100755..100644 --- a/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_menu_share_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..462e0e0 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..939ff4e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..8f89040 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..ccd53a3 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..0b1ae2d --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..c8e5efc4 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_solid_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..6cb8a0e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_solid_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png Binary files differnew file mode 100644 index 0000000..49b2669 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..201e21d --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png Binary files differnew file mode 100644 index 0000000..ac96200 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_inverse_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png Binary files differnew file mode 100644 index 0000000..d605d96 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..8ece2a9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..ae0b6b7 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png Binary files differnew file mode 100644 index 0000000..d3a3809 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_transparent_dark_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png Binary files differnew file mode 100644 index 0000000..7e6e24d --- /dev/null +++ b/core/res/res/drawable-xhdpi/ab_transparent_light_holo.9.png diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png Binary files differnew file mode 100644 index 0000000..8ded62f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png Binary files differnew file mode 100644 index 0000000..517e9f7 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_ab_back_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_account_list.png b/core/res/res/drawable-xhdpi/ic_menu_account_list.png Binary files differnew file mode 100644 index 0000000..ebe29b9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_account_list.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_add.png b/core/res/res/drawable-xhdpi/ic_menu_add.png Binary files differnew file mode 100644 index 0000000..7d498a9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_add.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_agenda.png b/core/res/res/drawable-xhdpi/ic_menu_agenda.png Binary files differnew file mode 100644 index 0000000..25e9f11 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_agenda.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_allfriends.png b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png Binary files differnew file mode 100644 index 0000000..20994ed --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_allfriends.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png Binary files differnew file mode 100644 index 0000000..96606de --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_always_landscape_portrait.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_archive.png b/core/res/res/drawable-xhdpi/ic_menu_archive.png Binary files differnew file mode 100644 index 0000000..b1be9d5 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_archive.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_attachment.png b/core/res/res/drawable-xhdpi/ic_menu_attachment.png Binary files differnew file mode 100644 index 0000000..aa41bd6 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_attachment.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_back.png b/core/res/res/drawable-xhdpi/ic_menu_back.png Binary files differnew file mode 100644 index 0000000..8ac4f64 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_back.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_block.png b/core/res/res/drawable-xhdpi/ic_menu_block.png Binary files differnew file mode 100644 index 0000000..e672395 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_block.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png Binary files differnew file mode 100644 index 0000000..53a279e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_blocked_user.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_btn_add.png b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png Binary files differnew file mode 100644 index 0000000..7d498a9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_btn_add.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_call.png b/core/res/res/drawable-xhdpi/ic_menu_call.png Binary files differnew file mode 100644 index 0000000..703a76b --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_call.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_camera.png b/core/res/res/drawable-xhdpi/ic_menu_camera.png Binary files differnew file mode 100644 index 0000000..7875aa3 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_camera.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cc.png b/core/res/res/drawable-xhdpi/ic_menu_cc.png Binary files differnew file mode 100644 index 0000000..50d686a --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_cc.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png Binary files differnew file mode 100644 index 0000000..c0b238c --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_chat_dashboard.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png Binary files differnew file mode 100644 index 0000000..8981d6f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_clear_playlist.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png Binary files differnew file mode 100644 index 0000000..d743d75 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_close_clear_cancel.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_compass.png b/core/res/res/drawable-xhdpi/ic_menu_compass.png Binary files differnew file mode 100644 index 0000000..1c2ad89 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_compass.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_compose.png b/core/res/res/drawable-xhdpi/ic_menu_compose.png Binary files differnew file mode 100644 index 0000000..bef190e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_compose.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy.png b/core/res/res/drawable-xhdpi/ic_menu_copy.png Binary files differnew file mode 100644 index 0000000..22761fc --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_copy.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png Binary files differnew file mode 100644 index 0000000..8014345 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png Binary files differnew file mode 100644 index 0000000..b5359a1 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_copy_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_crop.png b/core/res/res/drawable-xhdpi/ic_menu_crop.png Binary files differnew file mode 100644 index 0000000..d32daae --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_crop.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut.png b/core/res/res/drawable-xhdpi/ic_menu_cut.png Binary files differnew file mode 100644 index 0000000..efefcde --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_cut.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png Binary files differnew file mode 100644 index 0000000..180365f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png Binary files differnew file mode 100644 index 0000000..a31a06f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_cut_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_day.png b/core/res/res/drawable-xhdpi/ic_menu_day.png Binary files differnew file mode 100644 index 0000000..9eed1b2 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_day.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_delete.png b/core/res/res/drawable-xhdpi/ic_menu_delete.png Binary files differnew file mode 100644 index 0000000..65b9cae --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_delete.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_directions.png b/core/res/res/drawable-xhdpi/ic_menu_directions.png Binary files differnew file mode 100644 index 0000000..bdc0088 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_directions.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_edit.png b/core/res/res/drawable-xhdpi/ic_menu_edit.png Binary files differnew file mode 100644 index 0000000..fcdd71e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_edit.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_emoticons.png b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png Binary files differnew file mode 100644 index 0000000..af730fa --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_emoticons.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png Binary files differnew file mode 100644 index 0000000..ac76f3b --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_end_conversation.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_find.png b/core/res/res/drawable-xhdpi/ic_menu_find.png Binary files differnew file mode 100644 index 0000000..ccf2aab --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_find.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png Binary files differnew file mode 100644 index 0000000..3ede9e2 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png Binary files differnew file mode 100644 index 0000000..de20fa0 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_find_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_forward.png b/core/res/res/drawable-xhdpi/ic_menu_forward.png Binary files differnew file mode 100644 index 0000000..6463e7a --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_forward.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_friendslist.png b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png Binary files differnew file mode 100644 index 0000000..9200f87 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_friendslist.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_gallery.png b/core/res/res/drawable-xhdpi/ic_menu_gallery.png Binary files differnew file mode 100644 index 0000000..6b21e22 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_gallery.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_goto.png b/core/res/res/drawable-xhdpi/ic_menu_goto.png Binary files differnew file mode 100644 index 0000000..b925e69 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_goto.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_help.png b/core/res/res/drawable-xhdpi/ic_menu_help.png Binary files differnew file mode 100644 index 0000000..128c7e8 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_help.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png Binary files differnew file mode 100644 index 0000000..b961de9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_help_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_home.png b/core/res/res/drawable-xhdpi/ic_menu_home.png Binary files differnew file mode 100644 index 0000000..689f372 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_home.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_info_details.png b/core/res/res/drawable-xhdpi/ic_menu_info_details.png Binary files differnew file mode 100644 index 0000000..24ea543 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_info_details.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_invite.png b/core/res/res/drawable-xhdpi/ic_menu_invite.png Binary files differnew file mode 100644 index 0000000..d594607 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_invite.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_login.png b/core/res/res/drawable-xhdpi/ic_menu_login.png Binary files differnew file mode 100644 index 0000000..5095ed9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_login.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_manage.png b/core/res/res/drawable-xhdpi/ic_menu_manage.png Binary files differnew file mode 100644 index 0000000..d743624 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_manage.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_mapmode.png b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png Binary files differnew file mode 100644 index 0000000..0b62d08 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_mapmode.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_mark.png b/core/res/res/drawable-xhdpi/ic_menu_mark.png Binary files differnew file mode 100644 index 0000000..a5de6fb --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_mark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_month.png b/core/res/res/drawable-xhdpi/ic_menu_month.png Binary files differnew file mode 100644 index 0000000..099263b --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_month.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_more.png b/core/res/res/drawable-xhdpi/ic_menu_more.png Binary files differnew file mode 100644 index 0000000..c7a6538 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_more.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png Binary files differnew file mode 100644 index 0000000..2998d65 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png Binary files differnew file mode 100644 index 0000000..62659fa --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png Binary files differnew file mode 100644 index 0000000..341edaf --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_focused_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png Binary files differnew file mode 100644 index 0000000..81306ca --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png Binary files differnew file mode 100644 index 0000000..1f46e7a --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_normal_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png Binary files differnew file mode 100644 index 0000000..ca95b92 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_my_calendar.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_mylocation.png b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png Binary files differnew file mode 100644 index 0000000..b0a76a2 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_mylocation.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_myplaces.png b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png Binary files differnew file mode 100644 index 0000000..205848e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_myplaces.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_notifications.png b/core/res/res/drawable-xhdpi/ic_menu_notifications.png Binary files differnew file mode 100644 index 0000000..db80b57 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_notifications.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste.png b/core/res/res/drawable-xhdpi/ic_menu_paste.png Binary files differnew file mode 100644 index 0000000..a69f0eb --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_paste.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png Binary files differnew file mode 100644 index 0000000..6e7273f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png Binary files differnew file mode 100644 index 0000000..b7eedd9 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_paste_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_play_clip.png b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png Binary files differnew file mode 100644 index 0000000..f680fce --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_play_clip.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_preferences.png b/core/res/res/drawable-xhdpi/ic_menu_preferences.png Binary files differnew file mode 100644 index 0000000..02cfbad --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_preferences.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_recent_history.png b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png Binary files differnew file mode 100644 index 0000000..fc5e1fc --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_recent_history.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_refresh.png b/core/res/res/drawable-xhdpi/ic_menu_refresh.png Binary files differnew file mode 100644 index 0000000..9e9f10e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_refresh.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_report_image.png b/core/res/res/drawable-xhdpi/ic_menu_report_image.png Binary files differnew file mode 100644 index 0000000..26f7ff4 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_report_image.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_revert.png b/core/res/res/drawable-xhdpi/ic_menu_revert.png Binary files differnew file mode 100644 index 0000000..19c580f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_revert.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_rotate.png b/core/res/res/drawable-xhdpi/ic_menu_rotate.png Binary files differnew file mode 100644 index 0000000..98e19fe --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_rotate.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_save.png b/core/res/res/drawable-xhdpi/ic_menu_save.png Binary files differnew file mode 100644 index 0000000..62a66d8 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_save.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_search.png b/core/res/res/drawable-xhdpi/ic_menu_search.png Binary files differnew file mode 100644 index 0000000..5c18f9e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_search.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png Binary files differnew file mode 100644 index 0000000..d49c7e2 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png Binary files differnew file mode 100644 index 0000000..578cb24 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png Binary files differnew file mode 100644 index 0000000..7125557 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png Binary files differnew file mode 100644 index 0000000..c7728d4 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_send.png b/core/res/res/drawable-xhdpi/ic_menu_send.png Binary files differnew file mode 100644 index 0000000..6e5ec78 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_send.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_set_as.png b/core/res/res/drawable-xhdpi/ic_menu_set_as.png Binary files differnew file mode 100644 index 0000000..8689766 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_set_as.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png Binary files differnew file mode 100644 index 0000000..aa33c38 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_settings_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_share.png b/core/res/res/drawable-xhdpi/ic_menu_share.png Binary files differnew file mode 100644 index 0000000..fce1d35 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_share.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png Binary files differnew file mode 100644 index 0000000..af72732 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png Binary files differnew file mode 100644 index 0000000..79c162f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_share_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_slideshow.png b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png Binary files differnew file mode 100644 index 0000000..8740f37 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_slideshow.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png Binary files differnew file mode 100644 index 0000000..5736ff8 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_sort_alphabetically.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png Binary files differnew file mode 100644 index 0000000..fe3836c --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_sort_by_size.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_star.png b/core/res/res/drawable-xhdpi/ic_menu_star.png Binary files differnew file mode 100644 index 0000000..c051020 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_star.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png Binary files differnew file mode 100644 index 0000000..d71ed17 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_start_conversation.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_stop.png b/core/res/res/drawable-xhdpi/ic_menu_stop.png Binary files differnew file mode 100644 index 0000000..855af11 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_stop.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_today.png b/core/res/res/drawable-xhdpi/ic_menu_today.png Binary files differnew file mode 100644 index 0000000..e9ebc5e --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_today.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload.png b/core/res/res/drawable-xhdpi/ic_menu_upload.png Binary files differnew file mode 100644 index 0000000..94d1478 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_upload.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png Binary files differnew file mode 100644 index 0000000..508c354 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_upload_you_tube.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_view.png b/core/res/res/drawable-xhdpi/ic_menu_view.png Binary files differnew file mode 100644 index 0000000..e97c30df --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_view.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_week.png b/core/res/res/drawable-xhdpi/ic_menu_week.png Binary files differnew file mode 100644 index 0000000..2c3e761 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_week.png diff --git a/core/res/res/drawable-xhdpi/ic_menu_zoom.png b/core/res/res/drawable-xhdpi/ic_menu_zoom.png Binary files differnew file mode 100644 index 0000000..858aef5 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_menu_zoom.png diff --git a/core/res/res/layout-land/ssl_certificate.xml b/core/res/res/layout-land/ssl_certificate.xml index c3e6deb..4f8bd8e 100644 --- a/core/res/res/layout-land/ssl_certificate.xml +++ b/core/res/res/layout-land/ssl_certificate.xml @@ -23,6 +23,7 @@ android:id="@+id/body" android:layout_width="match_parent" android:layout_height="wrap_content" + android:gravity="left" android:orientation="vertical" > <!-- Placeholder for the success message or one or more warnings --> @@ -43,8 +44,7 @@ android:layout_weight="1" android:gravity="fill_horizontal" android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> + android:layout_marginRight="20dip"/> <TableLayout android:layout_width="match_parent" @@ -58,7 +58,8 @@ android:text="@string/issued_to" android:textStyle="bold" android:layout_height="wrap_content" - android:layout_width="wrap_content" + android:layout_width="match_parent" + android:layout_marginTop="12dip" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -68,12 +69,10 @@ <TextView android:id="@+id/to_common_header" android:text="@string/common_name" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/to_common" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -84,12 +83,10 @@ <TextView android:id="@+id/to_org_header" android:text="@string/org_name" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/to_org" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -100,15 +97,27 @@ <TextView android:id="@+id/to_org_unit_header" android:text="@string/org_unit" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/to_org_unit" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> + android:layout_marginBottom="7dip" /> + </TableRow> + + <!-- Serial number: --> + <TableRow> + <TextView + android:id="@+id/serial_number_header" + android:text="@string/serial_number" + android:layout_marginLeft="20dip" /> + + <TextView + android:id="@+id/serial_number" + android:layout_marginLeft="10dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> </TableRow> <!-- Issued by: --> @@ -117,7 +126,8 @@ android:text="@string/issued_by" android:textStyle="bold" android:layout_height="wrap_content" - android:layout_width="wrap_content" + android:layout_width="match_parent" + android:layout_marginTop="12dip" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -127,12 +137,10 @@ <TextView android:id="@+id/by_common_header" android:text="@string/common_name" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/by_common" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -143,12 +151,10 @@ <TextView android:id="@+id/by_org_header" android:text="@string/org_name" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/by_org" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -159,24 +165,23 @@ <TextView android:id="@+id/by_org_unit_header" android:text="@string/org_unit" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/by_org_unit" - android:gravity="left" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> + android:layout_marginBottom="7dip" /> </TableRow> <!-- Validity Dates: --> <TextView android:id="@+id/validity_header" android:layout_height="wrap_content" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:text="@string/validity_period" android:textStyle="bold" + android:layout_marginTop="12dip" android:layout_marginLeft="20dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -185,17 +190,15 @@ <TableRow> <TextView android:id="@+id/issued_on_header" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/issued_on" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/issued_on" android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" + android:layout_width="match_parent" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" android:layout_marginBottom="7dip" /> @@ -206,20 +209,68 @@ <TableRow> <TextView android:id="@+id/expires_on_header" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/expires_on" - android:gravity="left" android:layout_marginLeft="20dip" /> <TextView android:id="@+id/expires_on" android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" + android:layout_width="match_parent" + android:layout_marginLeft="10dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + </TableRow> + + <!-- Fingerprints: --> + <TextView + android:id="@+id/fingerprints" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/fingerprints" + android:textStyle="bold" + android:layout_marginTop="12dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- SHA-256 fingerprint: --> + <TableRow> + <TextView + android:id="@+id/sha256_fingerprint_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sha256_fingerprint" + android:layout_marginLeft="20dip" /> + + <TextView + android:id="@+id/sha256_fingerprint" + android:layout_height="wrap_content" + android:layout_width="match_parent" android:layout_marginLeft="10dip" android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> + android:layout_marginBottom="7dip" /> + + </TableRow> + + <!-- SHA-1 fingerprint: --> + <TableRow> + <TextView + android:id="@+id/sha1_fingerprint_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sha1_fingerprint" + android:layout_marginLeft="20dip" /> + + <TextView + android:id="@+id/sha1_fingerprint" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="10dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + </TableRow> </TableLayout> diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml index a8f0c22..dca6c52 100644 --- a/core/res/res/layout/action_menu_item_layout.xml +++ b/core/res/res/layout/action_menu_item_layout.xml @@ -21,8 +21,8 @@ android:addStatesFromChildren="true" android:gravity="center" android:focusable="true" - android:paddingLeft="12dip" - android:paddingRight="12dip" + android:paddingLeft="4dip" + android:paddingRight="4dip" style="?android:attr/actionButtonStyle"> <ImageButton android:id="@+id/imageButton" android:layout_width="wrap_content" @@ -45,6 +45,8 @@ android:textAppearance="?attr/actionMenuTextAppearance" style="?attr/buttonStyleSmall" android:textColor="?attr/actionMenuTextColor" + android:singleLine="true" + android:ellipsize="none" android:background="@null" android:paddingTop="4dip" android:paddingBottom="4dip" diff --git a/core/res/res/layout/ssl_certificate.xml b/core/res/res/layout/ssl_certificate.xml index ae661ce..dd89a2d 100644 --- a/core/res/res/layout/ssl_certificate.xml +++ b/core/res/res/layout/ssl_certificate.xml @@ -23,6 +23,7 @@ android:id="@+id/body" android:layout_width="match_parent" android:layout_height="wrap_content" + android:gravity="left" android:orientation="vertical" > <!-- Placeholder for the success message or one or more warnings --> @@ -43,200 +44,242 @@ android:layout_weight="1" android:gravity="fill_horizontal" android:layout_marginRight="20dip" + android:layout_marginLeft="20dip"/> + + <!-- Issued to: --> + <TextView + android:id="@+id/issued_to_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/issued_to" + android:textStyle="bold" + android:layout_marginTop="12dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Common name: --> + <TextView + android:id="@+id/to_common_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/common_name" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/to_common" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Organization: --> + <TextView + android:id="@+id/to_org_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/org_name" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/to_org" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Organizational unit: --> + <TextView + android:id="@+id/to_org_unit_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/org_unit" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/to_org_unit" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Serial number: --> + <TextView + android:id="@+id/serial_number_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/serial_number" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/serial_number" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Issued by: --> + <TextView + android:id="@+id/issued_to_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/issued_by" + android:textStyle="bold" + android:layout_marginTop="12dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Common name: --> + <TextView + android:id="@+id/by_common_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/common_name" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/by_common" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Organization: --> + <TextView + android:id="@+id/by_org_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/org_name" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/by_org" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Organizational unit: --> + <TextView + android:id="@+id/by_org_unit_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/org_unit" android:layout_marginLeft="20dip" - android:layout_marginBottom="12dip" /> - - <TableLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <!-- Issued to: --> - <TextView - android:id="@+id/issued_to_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/issued_to" - android:textStyle="bold" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Common name: --> - <TextView - android:id="@+id/to_common_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/common_name" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/to_common" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Organization: --> - <TextView - android:id="@+id/to_org_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/org_name" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/to_org" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Organizational unit: --> - <TextView - android:id="@+id/to_org_unit_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/org_unit" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/to_org_unit" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> - - <!-- Issued by: --> - <TextView - android:id="@+id/issued_to_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/issued_by" - android:textStyle="bold" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Common name: --> - <TextView - android:id="@+id/by_common_header" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/common_name" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/by_common" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Organization: --> - <TextView - android:id="@+id/by_org_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/org_name" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/by_org" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Organizational unit: --> - <TextView - android:id="@+id/by_org_unit_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/org_unit" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/by_org_unit" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> - - <!-- Validity Dates: --> - <TextView - android:id="@+id/validity_header" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/validity_period" - android:textStyle="bold" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Issued On: --> - <TextView - android:id="@+id/issued_on_header" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/issued_on" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/issued_on" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="10dip" /> - - <!-- Expires On: --> - <TextView - android:id="@+id/expires_on_header" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/expires_on" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" /> - - <TextView - android:id="@+id/expires_on" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:gravity="left" - android:layout_marginLeft="20dip" - android:layout_marginRight="20dip" - android:layout_marginBottom="12dip" /> - - </TableLayout> + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/by_org_unit" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Validity Dates: --> + <TextView + android:id="@+id/validity_header" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/validity_period" + android:textStyle="bold" + android:layout_marginTop="12dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Issued On: --> + <TextView + android:id="@+id/issued_on_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/issued_on" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/issued_on" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Expires On: --> + <TextView + android:id="@+id/expires_on_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/expires_on" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/expires_on" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- Fingerprints: --> + <TextView + android:id="@+id/fingerprints" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:text="@string/fingerprints" + android:textStyle="bold" + android:layout_marginTop="12dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- SHA-256 fingerprint: --> + <TextView + android:id="@+id/sha256_fingerprint_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sha256_fingerprint" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/sha256_fingerprint" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> + + <!-- SHA-1 fingerprint: --> + <TextView + android:id="@+id/sha1_fingerprint_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/sha1_fingerprint" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" /> + + <TextView + android:id="@+id/sha1_fingerprint" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginLeft="20dip" + android:layout_marginRight="20dip" + android:layout_marginBottom="7dip" /> </LinearLayout> diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml index 8206e79..57a2939 100644 --- a/core/res/res/values-w480dp/bools.xml +++ b/core/res/res/values-w480dp/bools.xml @@ -17,7 +17,6 @@ */ --> <resources> - <bool name="allow_action_menu_item_text_with_icon">true</bool> <bool name="action_bar_embed_tabs">true</bool> <bool name="split_action_bar_is_narrow">false</bool> </resources> diff --git a/core/res/res/values-w480dp/config.xml b/core/res/res/values-w480dp/config.xml new file mode 100644 index 0000000..269a9b4 --- /dev/null +++ b/core/res/res/values-w480dp/config.xml @@ -0,0 +1,21 @@ +<?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. +*/ +--> +<resources> + <bool name="config_allowActionMenuItemTextWithIcon">true</bool> +</resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index aa8c510..b92ce6a 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5210,6 +5210,10 @@ <attr name="divider" /> <!-- Specifies a background drawable for the action bar. --> <attr name="background" /> + <!-- Specifies a background drawable for a second stacked row of the action bar. --> + <attr name="backgroundStacked" format="reference" /> + <!-- Specifies a background drawable for the bottom component of a split action bar. --> + <attr name="backgroundSplit" format="reference" /> <!-- Specifies a layout for custom navigation. Overrides navigationMode. --> <attr name="customNavigationLayout" format="reference" /> <!-- Specifies a fixed height. --> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 03b332e..dd16bd0 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -696,13 +696,6 @@ <p>The default value of this attribute is <code>false</code>. --> <attr name="restoreAnyVersion" format="boolean" /> - <!-- The agent to use for a *full* backup of the package. Only system applications - can use this to override the ordinary FullBackupAgent with a custom implementation. - It's needed strictly for packages with strongly device-specific data, such as the - Settings provider. - --> - <attr name="fullBackupAgent" format="string" /> - <!-- The default install location defined by an application. --> <attr name="installLocation"> <!-- Let the system decide ideal install location --> @@ -800,7 +793,6 @@ <attr name="killAfterRestore" /> <attr name="restoreNeedsApplication" /> <attr name="restoreAnyVersion" /> - <attr name="fullBackupAgent" /> <attr name="neverEncrypt" /> <!-- Request that your application's processes be created with a large Dalvik heap. This applies to <em>all</em> processes diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index 9647bb7..e51fc66 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -15,7 +15,6 @@ --> <resources> - <bool name="allow_action_menu_item_text_with_icon">false</bool> <bool name="action_bar_embed_tabs">false</bool> <bool name="split_action_bar_is_narrow">true</bool> <bool name="preferences_prefer_dual_pane">false</bool> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 87b9be4..9f05cbc 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -650,4 +650,14 @@ autodetected from the Configuration. --> <bool name="config_showNavigationBar">false</bool> + <!-- Whether action menu items should be displayed in ALLCAPS or not. + Defaults to true. If this is not appropriate for specific locales + it should be disabled in that locale's resources. --> + <bool name="config_actionMenuItemAllCaps">true</bool> + + <!-- Whether action menu items should obey the "withText" showAsAction + flag. This may be set to false for situations where space is + extremely limited. --> + <bool name="config_allowActionMenuItemTextWithIcon">false</bool> + </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 54e484e..75acb37 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1714,10 +1714,6 @@ <public type="attr" name="switchTextOff" /> <public type="attr" name="switchPreferenceStyle" /> - <public type="style" name="TextAppearance.SuggestionHighlight" /> - <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" /> - <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" /> - <public type="attr" name="textSuggestionsWindowStyle" /> <public type="attr" name="textEditSuggestionsBottomWindowLayout" /> <public type="attr" name="textEditSuggestionsTopWindowLayout" /> @@ -1725,7 +1721,6 @@ <public type="attr" name="layoutDirection" /> - <public type="attr" name="fullBackupAgent" /> <public type="attr" name="suggestionsEnabled" /> <public type="attr" name="rowCount" /> @@ -1737,7 +1732,6 @@ <public type="attr" name="layout_row" /> <public type="attr" name="layout_rowSpan" /> - <public type="attr" name="layout_columnSpan" /> <public type="attr" name="layout_widthSpec" /> @@ -1778,14 +1772,38 @@ <public type="attr" name="actionBarSplitStyle" /> + <public type="attr" name="textDirection"/> + + <public type="attr" name="actionProviderClass" /> + + <public type="attr" name="backgroundStacked" /> + <public type="attr" name="backgroundSplit" /> + + <public type="style" name="TextAppearance.SuggestionHighlight" /> + <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" /> + <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" /> + <public type="style" name="Widget.Holo.Button.Borderless.Small" /> <public type="style" name="Widget.Holo.Light.Button.Borderless.Small" /> + <public type="style" name="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" /> + <public type="style" name="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" /> + <public type="style" name="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" /> + <public type="style" name="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" /> + <public type="style" name="Widget.Holo.ActionBar.Solid" /> + <public type="style" name="Widget.Holo.Light.ActionBar.Solid" /> + <public type="style" name="Widget.Holo.Light.ActionBar.Solid.Inverse" /> + <public type="style" name="Widget.Holo.Light.ActionBar.TabBar.Inverse" /> + <public type="style" name="Widget.Holo.Light.ActionBar.TabView.Inverse" /> + <public type="style" name="Widget.Holo.Light.ActionBar.TabText.Inverse" /> + <public type="style" name="Widget.Holo.Light.ActionMode.Inverse" /> + <public type="style" name="Theme.Holo.SolidActionBar" /> + <public type="style" name="Theme.Holo.Light.SolidActionBar" /> + <public type="style" name="Theme.Holo.Light.SolidActionBar.Inverse" /> + <public type="style" name="Theme.Holo.SolidActionBar.SplitActionBarWhenNarrow" /> + <public type="style" name="Theme.Holo.Light.SolidActionBar.SplitActionBarWhenNarrow" /> + <public type="style" name="Theme.Holo.Light.SolidActionBar.Inverse.SplitActionBarWhenNarrow" /> <public type="integer" name="status_bar_notification_info_maxnum" /> <public type="string" name="status_bar_notification_info_overflow" /> - <public type="attr" name="textDirection"/> - - <public type="attr" name="actionProviderClass" /> - </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9897c80..50f8df7 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2989,6 +2989,14 @@ <string name="issued_on">Issued on:</string> <!-- Label for an information field on an SSL Certificate Dialog --> <string name="expires_on">Expires on:</string> + <!-- Label for an information field on an SSL Certificate Dialog --> + <string name="serial_number">Serial number:</string> + <!-- Label for an information field on an SSL Certificate Dialog --> + <string name="fingerprints">Fingerprints:</string> + <!-- Label for an information field on an SSL Certificate Dialog --> + <string name="sha256_fingerprint">SHA-256 fingerprint:</string> + <!-- Label for an information field on an SSL Certificate Dialog --> + <string name="sha1_fingerprint">SHA-1 fingerprint:</string> <!-- Title for a button to expand the list of activities in ActivityChooserView [CHAR LIMIT=25] --> <string name="activity_chooser_view_see_all">See all...</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 5244b74..9ee4b6a 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1304,13 +1304,37 @@ <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item> </style> + <style name="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" + parent="TextAppearance.Holo.Medium.Inverse"> + <item name="android:textSize">@android:dimen/action_bar_title_text_size</item> + </style> + + <style name="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" + parent="TextAppearance.Holo.Small.Inverse"> + <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item> + </style> + <style name="TextAppearance.Holo.Widget.ActionMode"> </style> - <style name="TextAppearance.Holo.Widget.ActionMode.Title" parent="TextAppearance.Widget.ActionMode.Title"> + <style name="TextAppearance.Holo.Widget.ActionMode.Title" + parent="TextAppearance.Holo.Medium"> + <item name="android:textSize">@android:dimen/action_bar_title_text_size</item> + </style> + + <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle" + parent="TextAppearance.Holo.Small"> + <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item> </style> - <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle"> + <style name="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" + parent="TextAppearance.Holo.Medium.Inverse"> + <item name="android:textSize">@android:dimen/action_bar_title_text_size</item> + </style> + + <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" + parent="TextAppearance.Holo.Small.Inverse"> + <item name="android:textSize">@android:dimen/action_bar_subtitle_text_size</item> </style> <style name="TextAppearance.Holo.Widget.Switch" parent="TextAppearance.Holo.Small"> @@ -1839,7 +1863,22 @@ <style name="Widget.Holo.ActionBar" parent="Widget.ActionBar"> <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item> <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item> - <item name="android:background">@null</item> + <item name="android:background">@android:drawable/ab_transparent_dark_holo</item> + <item name="android:backgroundStacked">@android:drawable/ab_stacked_transparent_dark_holo</item> + <item name="android:backgroundSplit">@android:drawable/ab_bottom_transparent_dark_holo</item> + <item name="android:divider">?android:attr/dividerVertical</item> + <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item> + <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item> + <item name="android:progressBarPadding">32dip</item> + <item name="android:itemPadding">8dip</item> + </style> + + <style name="Widget.Holo.ActionBar.Solid"> + <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item> + <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item> + <item name="android:background">@android:drawable/ab_solid_dark_holo</item> + <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_dark_holo</item> + <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_dark_holo</item> <item name="android:divider">?android:attr/dividerVertical</item> <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item> <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item> @@ -2157,23 +2196,68 @@ <style name="Widget.Holo.Light.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText"> </style> + <style name="Widget.Holo.Light.ActionBar.TabView.Inverse"> + </style> + + <style name="Widget.Holo.Light.ActionBar.TabBar.Inverse"> + </style> + + <style name="Widget.Holo.Light.ActionBar.TabText.Inverse"> + <item name="android:textAppearance">@style/TextAppearance.Holo.Medium</item> + <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> + <item name="android:textSize">18sp</item> + </style> + <style name="Widget.Holo.Light.ActionMode" parent="Widget.Holo.ActionMode"> <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title</item> <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle</item> </style> + <style name="Widget.Holo.Light.ActionMode.Inverse" parent="Widget.ActionMode"> + <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title.Inverse</item> + <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse</item> + </style> + <style name="Widget.Holo.Light.ActionButton.CloseMode"> </style> <style name="Widget.Holo.Light.ActionBar" parent="Widget.Holo.ActionBar"> <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item> <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item> - <item name="android:background">@null</item> + <item name="android:background">@android:drawable/ab_transparent_light_holo</item> + <item name="android:backgroundStacked">@android:drawable/ab_stacked_transparent_light_holo</item> + <item name="android:backgroundSplit">@android:drawable/ab_bottom_transparent_light_holo</item> <item name="android:homeAsUpIndicator">@android:drawable/ic_ab_back_holo_light</item> <item name="android:progressBarStyle">@android:style/Widget.Holo.Light.ProgressBar.Horizontal</item> <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar</item> </style> + <style name="Widget.Holo.Light.ActionBar.Solid"> + <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item> + <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item> + <item name="android:background">@android:drawable/ab_solid_light_holo</item> + <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_light_holo</item> + <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_light_holo</item> + <item name="android:divider">?android:attr/dividerVertical</item> + <item name="android:progressBarStyle">@android:style/Widget.Holo.Light.ProgressBar.Horizontal</item> + <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.Light.ProgressBar</item> + <item name="android:progressBarPadding">32dip</item> + <item name="android:itemPadding">8dip</item> + </style> + + <style name="Widget.Holo.Light.ActionBar.Solid.Inverse"> + <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title.Inverse</item> + <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse</item> + <item name="android:background">@android:drawable/ab_solid_dark_holo</item> + <item name="android:backgroundStacked">@android:drawable/ab_stacked_solid_dark_holo</item> + <item name="android:backgroundSplit">@android:drawable/ab_bottom_solid_inverse_holo</item> + <item name="android:divider">@android:drawable/list_divider_holo_dark</item> + <item name="android:progressBarStyle">@android:style/Widget.Holo.ProgressBar.Horizontal</item> + <item name="android:indeterminateProgressStyle">@android:style/Widget.Holo.ProgressBar</item> + <item name="android:progressBarPadding">32dip</item> + <item name="android:itemPadding">8dip</item> + </style> + <!-- Animation Styles --> <style name="Animation.Holo" parent="Animation"> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 78e9975..23111e6 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -283,7 +283,7 @@ <item name="actionBarSplitStyle">?android:attr/actionBarStyle</item> <item name="actionBarSize">@dimen/action_bar_default_height</item> <item name="actionModePopupWindowStyle">?android:attr/popupWindowStyle</item> - <item name="actionMenuTextAppearance">?android:attr/textAppearanceMedium</item> + <item name="actionMenuTextAppearance">?android:attr/textAppearanceSmall</item> <item name="actionMenuTextColor">?android:attr/textColorPrimary</item> <item name="dividerVertical">@drawable/divider_vertical_dark</item> @@ -1365,6 +1365,71 @@ </style> + <!-- Variant of the holographic (dark) theme that has a solid (opaque) action bar. --> + <style name="Theme.Holo.SolidActionBar"> + <item name="android:actionBarStyle">@android:style/Widget.Holo.ActionBar.Solid</item> + <item name="android:windowContentOverlay">@android:drawable/ab_solid_shadow_holo</item> + </style> + + <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar. --> + <style name="Theme.Holo.Light.SolidActionBar"> + <item name="android:actionBarStyle">@android:style/Widget.Holo.Light.ActionBar.Solid</item> + <item name="android:windowContentOverlay">@android:drawable/ab_solid_shadow_holo</item> + </style> + + <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar + with an inverse color profile. The dark action bar sharply stands out against + the light content. --> + <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="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item> + <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item> + <item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item> + <item name="actionModeBackground">@android:drawable/cab_background_holo_dark</item> + <item name="actionModeCloseDrawable">@android:drawable/cab_ic_close_holo</item> + <item name="actionBarTabStyle">@style/Widget.Holo.Light.ActionBar.TabView.Inverse</item> + <item name="actionBarTabBarStyle">@style/Widget.Holo.Light.ActionBar.TabBar.Inverse</item> + <item name="actionBarTabTextStyle">@style/Widget.Holo.Light.ActionBar.TabText.Inverse</item> + <item name="actionMenuTextColor">?android:attr/textColorPrimaryInverse</item> + <item name="actionModeStyle">@style/Widget.Holo.Light.ActionMode.Inverse</item> + <item name="actionModeCloseButtonStyle">@style/Widget.Holo.ActionButton.CloseMode</item> + <item name="actionModePopupWindowStyle">@android:style/Widget.Holo.PopupWindow.ActionMode</item> + + <item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_dark</item> + <item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_dark</item> + <item name="actionModePasteDrawable">@android:drawable/ic_menu_paste_holo_dark</item> + <item name="actionModeSelectAllDrawable">@android:drawable/ic_menu_selectall_holo_dark</item> + <item name="actionModeShareDrawable">@android:drawable/ic_menu_share_holo_dark</item> + <item name="actionModeFindDrawable">@android:drawable/ic_menu_find_holo_dark</item> + <item name="actionModeWebSearchDrawable">@android:drawable/ic_menu_search_holo_dark</item> + </style> + + <!-- Variant of the holographic (dark) theme that has a solid + (opaque) action bar. The action bar will split across both + the top and bottom of the screen when the screen is + especially constrained for horizontal space. --> + <style name="Theme.Holo.SolidActionBar.SplitActionBarWhenNarrow"> + <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item> + </style> + + <!-- Variant of the holographic (light) theme that has a solid + (opaque) action bar. The action bar will split across both + the top and bottom of the screen when the screen is + especially constrained for horizontal space. --> + <style name="Theme.Holo.Light.SolidActionBar.SplitActionBarWhenNarrow"> + <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item> + </style> + + <!-- Variant of the holographic (light) theme that has a solid (opaque) action bar + with an inverse color profile. The dark action bar sharply stands out against + the light content. The action bar will split across both the top and bottom of + the screen when the screen is especially constrained for horizontal space. --> + <style name="Theme.Holo.Light.SolidActionBar.Inverse.SplitActionBarWhenNarrow"> + <item name="android:windowSplitActionBar">@android:bool/split_action_bar_is_narrow</item> + </style> + <!-- Variant of the holographic (dark) theme with no action bar. --> <style name="Theme.Holo.NoActionBar"> <item name="android:windowActionBar">false</item> diff --git a/docs/html/guide/topics/graphics/index.jd b/docs/html/guide/topics/graphics/index.jd index be1b0fc..2490e39 100644 --- a/docs/html/guide/topics/graphics/index.jd +++ b/docs/html/guide/topics/graphics/index.jd @@ -14,13 +14,20 @@ page.title=Graphics </ol> </li> </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}guide/topics/graphics/opengl.html">3D with OpenGL</a></li> + <li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li> + </ol> </div> </div> -<p>Android graphics are powered by a custom 2D graphics library and OpenGL ES 1.0 -for high performance 3D graphics. The most common 2D graphics APIs can be found in the -{@link android.graphics.drawable drawable package}. OpenGL APIs are available -from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES package}, -plus some Android {@link android.opengl OpenGL utilities}.</p> + +<p>Android graphics are powered by a custom 2D graphics library, and the framework provides +support for high performance 3D graphics in the form of OpenGL ES and RenderScript. The most +common 2D graphics APIs can be found in the {@link android.graphics.drawable drawable package}. +OpenGL APIs are available from the Khronos {@link javax.microedition.khronos.opengles OpenGL ES} and +the {@link android.opengl} packages. The RenderScript APIs are available in the +{@link android.renderscript} package.</p> <p>When starting a project, it's important to consider exactly what your graphical demands will be. Varying graphical tasks are best accomplished with varying techniques. For example, graphics and animations @@ -32,10 +39,10 @@ and which tasks they're best suited for.</p> <p>If you're specifically looking for information on drawing 3D graphics, this page won't help a lot. However, the information below about how to <a href="#draw-with-canvas">Draw with a -Canvas</a> (and the section on SurfaceView), -will give you a quick idea of how you should draw to the View hierarchy. For more information -on Android's 3D graphic utilities (provided by the OpenGL ES API), -read <a href="opengl.html">3D with OpenGL</a> and refer to other OpenGL documentation.</p> +Canvas</a> (and the section on SurfaceView), will give you a quick idea of how you should draw to +the View hierarchy. For more information on Android's 3D graphics APIs, see +the <a href="opengl.html">3D with OpenGL</a> and +<a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> documents.</p> <h2 id="options">Consider your Options</h2> diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd index 9f88954..cc467f2 100644 --- a/docs/html/guide/topics/graphics/opengl.jd +++ b/docs/html/guide/topics/graphics/opengl.jd @@ -3,51 +3,215 @@ parent.title=Graphics parent.link=index.html @jd:body +<div id="qv-wrapper"> + <div id="qv"> + <h2>In this document</h2> + + <ol> + <li><a href="#basics">The Basics</a></li> + <li><a href="#compatibility">OpenGL Versions and Device Compatibility</a> + <ol> + <li><a href="#textures">Texture Compression Support</a></li> + <li><a href="#declare-compression">Declaring Use of Compressed Textures</a></li> + </ol> + </li> + </ol> + <h2>Key classes</h2> + <ol> + <li>{@link android.opengl.GLSurfaceView}</li> + <li>{@link android.opengl.GLSurfaceView.Renderer}</li> + <li>{@link javax.microedition.khronos.opengles}</li> + <li>{@link android.opengl}</li> + </ol> + <h2>Related Samples</h2> + <ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ +GLSurfaceViewActivity.html">GLSurfaceViewActivity</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ +GLES20Activity.html">GLES20Activity</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ +TouchRotateActivity.html">TouchRotateActivity</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ +CompressedTextureActivity.html">Compressed Textures</a></li> + </ol> + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}resources/articles/glsurfaceview.html">Introducing +GLSurfaceView</a></li> + <li><a href="http://www.khronos.org/opengles/">OpenGL ES</a></li> + <li><a href="http://www.khronos.org/opengles/1_X/">OpenGL ES 1.x Specification</a></li> + <li><a href="http://www.khronos.org/opengles/2_X/">OpenGL ES 2.x specification</a></li> + </ol> + </div> +</div> -<p>Android includes support for high performance 3D graphics -via the OpenGL API—specifically, the OpenGL ES API.</p> +<p>Android includes support for high performance 2D and 3D graphics with the Open Graphics Library +(OpenGL) API—specifically, the OpenGL ES API. OpenGL is a cross-platform graphics API that +specifies a standard software interface for 3D graphics processing hardware. OpenGL ES is a flavor +of the OpenGL specification intended for embedded devices. The OpenGL ES 1.0 and 1.1 API +specifications have been supported since Android 1.0. Beginning with Android 2.2 (API +Level 8), the framework supports the OpenGL ES 2.0 API specification.</p> -<p>OpenGL ES is a flavor of the OpenGL specification intended for embedded devices. Versions of <a -href="http://www.khronos.org/opengles/">OpenGL ES</a> are loosely peered to versions of the primary -OpenGL standard. Beginning with Android 2.2, the platform supports OpenGL ES 2.0 (with -backward compatibility support for OpenGL ES 1.1). For information about the relative number of -Android-powered devices that support a given version of OpenGL ES, see the <a -href="http://developer.android.com/resources/dashboard/opengl.html">OpenGL ES Versions</a> -dashboard.</p> +<p class="note"><b>Note:</b> The specific API provided by the Android framework is similar to the + J2ME JSR239 OpenGL ES API, but is not identical. If you are familiar with J2ME JSR239 + specification, be alert for variations.</p> -<p>The specific API provided by Android is similar to the J2ME JSR239 OpenGL -ES API. However, it may not be identical, so watch out for deviations.</p> -<h2>Using the API</h2> +<h2 id="basics">The Basics</h2> -<p>Here's how to use the API at an extremely high level:</p> +<p>Android supports OpenGL both through its framework API and the Native Development +Kit (NDK). This topic focuses on the Android framework interfaces. For more information about the +NDK, see the <a href="{@docRoot}sdk/ndk/index.html">Android NDK</a>. -<ol> -<li>Write a custom {@link android.view.View} subclass.</li> -<li>Obtain a handle to an OpenGLContext, which provides access to the OpenGL functionality.</li> -<li>In your View's {@link android.view.View#onDraw onDraw()} method, get a handle to a GL object, -and use its methods to perform GL operations.</li> -</ol> +<p> + There are two foundational classes in the Android framework that let you create and manipulate +graphics with the OpenGL ES API: {@link android.opengl.GLSurfaceView} and {@link +android.opengl.GLSurfaceView.Renderer}. If your goal is to use OpenGL in your Android application, +understanding how to implement these classes in an activity should be your first objective. +</p> + +<dl> + <dt>{@link android.opengl.GLSurfaceView}</dt> + <dd>This class is a container on which you can draw and manipulate objects using OpenGL API calls. + This class is similar in function to a {@link android.view.SurfaceView}, except that it is + specifically for use with OpenGL. You can use this class by simply creating an instance of + {@link android.opengl.GLSurfaceView} and adding your + {@link android.opengl.GLSurfaceView.Renderer Renderer} to it. However, if you want to capture + touch screen events, you should extend the {@link android.opengl.GLSurfaceView} class to + implement the touch listeners, as shown in the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity +.html">TouchRotateActivity</a> sample.</dd> + + <dt>{@link android.opengl.GLSurfaceView.Renderer}</dt> + <dd>This interface defines the methods required for drawing graphics in an OpenGL {@link + android.opengl.GLSurfaceView}. You must provide an implementation of this interface as a + separate class and attach it to your {@link android.opengl.GLSurfaceView} instance using + {@link android.opengl.GLSurfaceView#setRenderer(android.opengl.GLSurfaceView.Renderer) + GLSurfaceView.setRenderer()}. + + <p>The {@link android.opengl.GLSurfaceView.Renderer} interface requires that you implement the + following methods:</p> + <ul> + <li> + {@link + android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10, + javax.microedition.khronos.egl.EGLConfig) onSurfaceCreated()}: The system calls this + method once, when creating the {@link android.opengl.GLSurfaceView}. Use this method to perform + actions that need to happen only once, such as setting OpenGL environment parameters or + initializing OpenGL graphic objects. + </li> + <li> + {@link + android.opengl.GLSurfaceView.Renderer#onDrawFrame(javax.microedition.khronos.opengles.GL10) + onDrawFrame()}: The system calls this method on each redraw of the {@link + android.opengl.GLSurfaceView}. Use this method as the primary execution point for + drawing (and re-drawing) graphic objects.</li> + <li> + {@link + android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(javax.microedition.khronos.opengles.GL10, + int, int) onSurfaceChanged()}: The system calls this method when the {@link + android.opengl.GLSurfaceView} geometry changes, including changes in size of the {@link + android.opengl.GLSurfaceView} or orientation of the device screen. For example, the system calls + this method when the device changes from portrait to landscape orientation. Use this method to + respond to changes in the {@link android.opengl.GLSurfaceView} container. + </li> + </ul> + </dd> +</dl> + +<p>Once you have established a container view for OpenGL using {@link +android.opengl.GLSurfaceView} and {@link android.opengl.GLSurfaceView.Renderer}, you can begin +calling OpenGL APIs using the following classes:</p> + +<ul> + <li>OpenGL ES 1.0/1.1 API Packages + <ul> + <li>{@link javax.microedition.khronos.opengles} - This package provides the standard +implementation of OpenGL ES 1.0 and 1.1. + <ul> + <li>{@link javax.microedition.khronos.opengles.GL10}</li> + <li>{@link javax.microedition.khronos.opengles.GL10Ext}</li> + <li>{@link javax.microedition.khronos.opengles.GL11}</li> + <li>{@link javax.microedition.khronos.opengles.GL11Ext}</li> + <li>{@link javax.microedition.khronos.opengles.GL11ExtensionPack}</li> + </ul> + </li> + <li>{@link android.opengl} - This package provides a static interface to the OpenGL classes + above. These interfaces were added with Android 1.6 (API Level 4). + <ul> + <li>{@link android.opengl.GLES10}</li> + <li>{@link android.opengl.GLES10Ext}</li> + <li>{@link android.opengl.GLES11}</li> + <li>{@link android.opengl.GLES10Ext}</li> + </ul> + </li> + </ul> + </li> + <li>OpenGL ES 2.0 API Class + <ul> + <li>{@link android.opengl.GLES20 android.opengl.GLES20}</li> + </ul> + </li> +</ul> -<p>Several samples using OpenGL ES are available in the <a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html">API -Demos</a> sample application. +<h2 id="compatibility">OpenGL Versions and Device Compatibility</h2> + +<p> + The OpenGL ES 1.0 and 1.1 API specifications have been supported since Android 1.0. +Beginning with Android 2.2 (API Level 8), the framework supports the OpenGL ES 2.0 API +specification. OpenGL ES 2.0 is supported by most Android devices and is recommended for new +applications being developed with OpenGL. For information about the relative number of +Android-powered devices that support a given version of OpenGL ES, see the <a +href="{@docRoot}resources/dashboard/opengl.html">OpenGL ES Versions Dashboard</a>.</p> + +<h3 id="textures">Texture compression support</h3> +<p>Texture compression can significantly increase the performance of your OpenGL application by +reducing memory requirements and making more efficient use of memory bandwidth. The Android +framework provides support for the ETC1 compression format as a standard feature, including a {@link +android.opengl.ETC1Util} utility class and the {@code etc1tool} compression tool (located in your +Android SDK at {@code <sdk>/tools/}).</p> + +<p>For an example of an Android application that uses texture compression, see the <a +href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/ +CompressedTextureActivity.html">CompressedTextureActivity</a> code sample. </p> -<p>A summary of how to actually write 3D applications using OpenGL is -beyond the scope of this text and is left as an exercise for the reader.</p> +<p>To check if the ETC1 format is supported on a device, call the {@link +android.opengl.ETC1Util#isETC1Supported() ETC1Util.isETC1Supported()} method.</p> -<h2>Links to Additional Information</h2> +<p class="note"><b>Note:</b> The ETC1 texture compression format does not support textures with an +alpha channel. If your application requires textures with an alpha channel, you should +investigate other texture compression formats available on your target devices.</p> -<p>Information about OpenGL ES can be -found at <a title="http://www.khronos.org/opengles/" -href="http://www.khronos.org/opengles/">http://www.khronos.org/opengles/</a>.</p> +<p>Beyond the ETC1 format, Android devices have varied support for texture compression based on +their GPU chipsets. You should investigate texture compression support on the the devices you are +are targeting to determine what compression types your application should support.</p> -<p>Information specifically -about OpenGL ES 1.0 (including a detailed specification) can be found -at <a title="http://www.khronos.org/opengles/1_X/" -href="http://www.khronos.org/opengles/1_X/">http://www.khronos.org/opengles/1_X/</a>.</p> +<p>To determine if texture compression formats other than ETC1 are supported on a particular +device:</p> +<ol> + <li>Run the following code on your target devices to determine what texture compression +formats are supported: +<pre> + String extensions = javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS); +</pre> + <p class="warning"><b>Warning:</b> The results of this call vary by device! You must run this +call on several target devices to determine what compression types are commonly supported on +your target devices.</p> + </li> + <li>Review the output of this method to determine what extensions are supported on the +device.</li> +</ol> -<p>The documentation for the Android OpenGL ES implementations are available in {@link -android.opengl} and {@link javax.microedition.khronos.opengles}.</p> +<h3 id="declare-compression">Declaring compressed textures</h3> +<p>Once you have decided which texture compression types your application will support, you +must declare them in your manifest file using <a +href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html"> +<supports-gl-texture></a>. Declaring this information in your manifest file hides your +application from users with devices that do not support at least one of your declared +compression types. For more information on how Android Market filtering works for texture +compressions, see the <a +href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html#market-texture-filtering"> +Android Market and texture compression filtering</a> section of the {@code +<supports-gl-texture>} documentation. diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd index 2e172f5..b5a3f30 100644 --- a/docs/html/guide/topics/usb/adk.jd +++ b/docs/html/guide/topics/usb/adk.jd @@ -326,7 +326,7 @@ page.title=Android Open Accessory Development Kit <li>To open the firmware code (a sketch), click <strong>File > Open</strong> and select <code>firmware/demokit/demokit.pde</code>.</li> - <li>Click <strong>Sketch > Compile/Verify</strong> to ensure that the sketch has no + <li>Click <strong>Sketch > Verify/Compile</strong> to ensure that the sketch has no errors.</li> <li>Select <strong>File > Upload to I/O Board</strong>. When Arduino outputs <strong>Done @@ -356,7 +356,8 @@ page.title=Android Open Accessory Development Kit <li>In the <strong>Project name:</strong> field, type DemoKit.</li> <li>Choose <strong>Create project from existing source</strong>, click <strong>Browse</strong>, - select the <code>app</code> directory, and click <strong>Finish</strong>.</li> + select the <code>app</code> directory, click <strong>Open</strong> to close that dialog and then + click <strong>Finish</strong>.</li> <li>For Build Target, select <strong>Google APIs</strong> (Platform 2.3.3, API Level 10). diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index e8c9ae7..0fc10bf 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -726,6 +726,16 @@ var ANDROID_RESOURCES = [ en: 'Binding data to views using XML Adapters examples.' } }, + { + tags: ['sample', 'new', 'accessibility'], + path: 'samples/TtsEngine/index.html', + title: { + en: 'Text To Speech Engine' + }, + description: { + en: 'An example Text To Speech engine written using the android text to speech engine API.' + } + }, ///////////////// /// TUTORIALS /// diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index 28f305d..9aa6700 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -53,6 +53,7 @@ enum { METADATA_KEY_VIDEO_HEIGHT = 19, METADATA_KEY_BITRATE = 20, METADATA_KEY_TIMED_TEXT_LANGUAGES = 21, + METADATA_KEY_IS_DRM = 22, // Add more here... }; diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h index a82106e..eb45237 100644 --- a/include/media/stagefright/MediaExtractor.h +++ b/include/media/stagefright/MediaExtractor.h @@ -56,7 +56,12 @@ public: virtual uint32_t flags() const; // for DRM - virtual void setDrmFlag(bool flag) {}; + virtual void setDrmFlag(bool flag) { + mIsDrm = flag; + }; + virtual bool getDrmFlag() { + return mIsDrm; + } virtual char* getDrmTrackInfo(size_t trackID, int *len) { return NULL; } @@ -66,6 +71,8 @@ protected: virtual ~MediaExtractor() {} private: + bool mIsDrm; + MediaExtractor(const MediaExtractor &); MediaExtractor &operator=(const MediaExtractor &); }; diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h index e1b6b57..d3b2062 100644 --- a/include/surfaceflinger/IGraphicBufferAlloc.h +++ b/include/surfaceflinger/IGraphicBufferAlloc.h @@ -37,7 +37,7 @@ public: /* Create a new GraphicBuffer for the client to use. */ virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) = 0; + PixelFormat format, uint32_t usage, status_t* error) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/utils/threads.h b/include/utils/threads.h index 0bd69cf..c8e9c04 100644 --- a/include/utils/threads.h +++ b/include/utils/threads.h @@ -133,13 +133,13 @@ extern pid_t androidGetTid(); // Change the scheduling group of a particular thread. The group // should be one of the ANDROID_TGROUP constants. Returns BAD_VALUE if // grp is out of range, else another non-zero value with errno set if -// the operation failed. +// the operation failed. Thread ID zero means current thread. extern int androidSetThreadSchedulingGroup(pid_t tid, int grp); // Change the priority AND scheduling group of a particular thread. The priority // should be one of the ANDROID_PRIORITY constants. Returns INVALID_OPERATION // if the priority set failed, else another value if just the group set failed; -// in either case errno is set. +// in either case errno is set. Thread ID zero means current thread. extern int androidSetThreadPriority(pid_t tid, int prio); #ifdef __cplusplus @@ -510,6 +510,10 @@ public: // that case. status_t requestExitAndWait(); + // Wait until this object's thread exits. Returns immediately if not yet running. + // Do not call from this object's thread; will return WOULD_BLOCK in that case. + status_t join(); + protected: // exitPending() returns true if requestExit() has been called. bool exitPending() const; diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index e91bcab..6229331 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -81,6 +81,13 @@ import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore; * avoid prompting the user with {@link #choosePrivateKeyAlias * choosePrivateKeyAlias} on subsequent connections. If the alias is * no longer valid, null will be returned on lookups using that value + * + * <p>An application can request the installation of private keys and + * certificates via the {@code Intent} provided by {@link + * #createInstallIntent}. Private keys installed via this {@code + * Intent} will be accessible via {@link #choosePrivateKeyAlias} while + * Certificate Authority (CA) certificates will be trusted by all + * applications through the default {@code X509TrustManager}. */ // TODO reference intent for credential installation when public public final class KeyChain { @@ -135,8 +142,6 @@ public final class KeyChain { /** * Optional extra to specify a {@code String} credential name on * the {@code Intent} returned by {@link #createInstallIntent}. - * - * @hide TODO make public */ // Compatible with old com.android.certinstaller.CredentialHelper.CERT_NAME_KEY public static final String EXTRA_NAME = "name"; @@ -150,8 +155,6 @@ public final class KeyChain { * * <p>{@link #EXTRA_NAME} may be used to provide a default alias * name for the installed certificate. - * - * @hide TODO make public */ // Compatible with old android.security.Credentials.CERTIFICATE public static final String EXTRA_CERTIFICATE = "CERT"; @@ -161,7 +164,7 @@ public final class KeyChain { * {@link #createInstallIntent} to specify a PKCS#12 key store to * install. The extra value should be a {@code byte[]}. The bytes * may come from an external source or be generated with {@link - * KeyStore#store} on a "PKCS12" instance. + * java.security.KeyStore#store} on a "PKCS12" instance. * * <p>The user will be prompted for the password to load the key store. * @@ -171,8 +174,6 @@ public final class KeyChain { * * <p>{@link #EXTRA_NAME} may be used to provide a default alias * name for the installed credentials. - * - * @hide TODO make public */ // Compatible with old android.security.Credentials.PKCS12 public static final String EXTRA_PKCS12 = "PKCS12"; @@ -186,15 +187,13 @@ public final class KeyChain { * <p>Alternatively, {@link #EXTRA_CERTIFICATE} or {@link * #EXTRA_PKCS12} maybe used to specify the bytes of an X.509 * certificate or a PKCS#12 key store for installation. These - * extras may be combined with {@link EXTRA_NAME} to provide a + * extras may be combined with {@link #EXTRA_NAME} to provide a * default alias name for credentials being installed. * * <p>When used with {@link Activity#startActivityForResult}, * {@link Activity#RESULT_OK} will be returned if a credential was * successfully installed, otherwise {@link * Activity#RESULT_CANCELED} will be returned. - * - * @hide TODO make public with createInstallIntent, EXTRA_NAME, EXTRA_CERTIFICATE, EXTRA_PKCS12 */ public static Intent createInstallIntent() { Intent intent = new Intent(ACTION_INSTALL); diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp index 0cd51da..30f8d00 100644 --- a/libs/gui/IGraphicBufferAlloc.cpp +++ b/libs/gui/IGraphicBufferAlloc.cpp @@ -43,7 +43,7 @@ public: } virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) { + PixelFormat format, uint32_t usage, status_t* error) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor()); data.writeInt32(w); @@ -52,14 +52,15 @@ public: data.writeInt32(usage); remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply); sp<GraphicBuffer> graphicBuffer; - bool nonNull = (bool)reply.readInt32(); - if (nonNull) { + status_t result = reply.readInt32(); + if (result == NO_ERROR) { graphicBuffer = new GraphicBuffer(); reply.read(*graphicBuffer); // reply.readStrongBinder(); // here we don't even have to read the BufferReference from // the parcel, it'll die with the parcel. } + *error = result; return graphicBuffer; } }; @@ -91,8 +92,10 @@ status_t BnGraphicBufferAlloc::onTransact( uint32_t h = data.readInt32(); PixelFormat format = data.readInt32(); uint32_t usage = data.readInt32(); - sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage)); - reply->writeInt32(result != 0); + status_t error; + sp<GraphicBuffer> result = + createGraphicBuffer(w, h, format, usage, &error); + reply->writeInt32(error); if (result != 0) { reply->write(*result); // We add a BufferReference to this parcel to make sure the diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 3bf6477..886a3fb 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -352,11 +352,13 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, ((uint32_t(buffer->usage) & usage) != usage)) { usage |= GraphicBuffer::USAGE_HW_TEXTURE; + status_t error; sp<GraphicBuffer> graphicBuffer( - mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage)); + mGraphicBufferAlloc->createGraphicBuffer( + w, h, format, usage, &error)); if (graphicBuffer == 0) { LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed"); - return NO_MEMORY; + return error; } if (updateFormat) { mPixelFormat = format; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 450cdf1..ce587b3 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -31,13 +31,13 @@ protected: ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); mSurfaceControl = mComposerClient->createSurface( - String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGB_888, 0); + String8("Test Surface"), 0, 32, 32, PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(mSurfaceControl != NULL); ASSERT_TRUE(mSurfaceControl->isValid()); SurfaceComposerClient::openGlobalTransaction(); - ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff)); ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); SurfaceComposerClient::closeGlobalTransaction(); @@ -84,7 +84,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { PixelFormat fmt=0; sp<ISurfaceComposer> sf(ComposerService::getComposerService()); ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, - 40000)); + 0x7fffffff)); ASSERT_TRUE(heap != NULL); // Set the PROTECTED usage bit and verify that the screenshot fails. Note @@ -94,6 +94,18 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { GRALLOC_USAGE_PROTECTED)); ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3)); ANativeWindowBuffer* buf = 0; + + status_t err = anw->dequeueBuffer(anw.get(), &buf); + if (err) { + // we could fail if GRALLOC_USAGE_PROTECTED is not supported. + // that's okay as long as this is the reason for the failure. + // try again without the GRALLOC_USAGE_PROTECTED bit. + ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0)); + ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); + return; + } + ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf)); + for (int i = 0; i < 4; i++) { // Loop to make sure SurfaceFlinger has retired a protected buffer. ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf)); @@ -103,7 +115,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { heap = 0; w = h = fmt = 0; ASSERT_EQ(INVALID_OPERATION, sf->captureScreen(0, &heap, &w, &h, &fmt, - 64, 64, 0, 40000)); + 64, 64, 0, 0x7fffffff)); ASSERT_TRUE(heap == NULL); // XXX: This should not be needed, but it seems that the new buffers don't @@ -126,7 +138,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersFail) { heap = 0; w = h = fmt = 0; ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 64, 64, 0, - 40000)); + 0x7fffffff)); ASSERT_TRUE(heap != NULL); } diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index 15bb1d2..50312e7 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -316,6 +316,10 @@ int androidSetThreadSchedulingGroup(pid_t tid, int grp) #if defined(HAVE_PTHREADS) pthread_once(&gDoSchedulingGroupOnce, checkDoSchedulingGroup); if (gDoSchedulingGroup) { + // set_sched_policy does not support tid == 0 + if (tid == 0) { + tid = androidGetTid(); + } if (set_sched_policy(tid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ? SP_BACKGROUND : SP_FOREGROUND)) { return PERMISSION_DENIED; @@ -842,6 +846,25 @@ status_t Thread::requestExitAndWait() return mStatus; } +status_t Thread::join() +{ + Mutex::Autolock _l(mLock); + if (mThread == getThreadId()) { + LOGW( + "Thread (this=%p): don't call join() from this " + "Thread object's thread. It's a guaranteed deadlock!", + this); + + return WOULD_BLOCK; + } + + while (mRunning == true) { + mThreadExitedCondition.wait(mLock); + } + + return mStatus; +} + bool Thread::exitPending() const { Mutex::Autolock _l(mLock); diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 7634c6c..6df2f73 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -214,7 +214,7 @@ public class MediaFile { addFileType("PNG", FILE_TYPE_PNG, "image/png", MtpConstants.FORMAT_PNG); addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", MtpConstants.FORMAT_BMP); addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp"); - addFileType("WEBP", FILE_TYPE_WBMP, "image/webp"); + addFileType("WEBP", FILE_TYPE_WEBP, "image/webp"); addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST); addFileType("M3U", FILE_TYPE_M3U, "application/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST); diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 7ebedaf..10694c3 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -453,5 +453,10 @@ public class MediaMetadataRetriever * @hide */ public static final int METADATA_KEY_TIMED_TEXT_LANGUAGES = 21; + /** + * If this key exists the media is drm-protected. + * @hide + */ + public static final int METADATA_KEY_IS_DRM = 22; // Add more here... } diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 790eaa3..c55338a 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -422,6 +422,7 @@ public class MediaScanner private long mFileSize; private String mWriter; private int mCompilation; + private boolean mIsDrm; private boolean mNoMedia; // flag to suppress file from appearing in media tables public FileCacheEntry beginFile(String path, String mimeType, long lastModified, @@ -497,6 +498,7 @@ public class MediaScanner mLastModified = lastModified; mWriter = null; mCompilation = 0; + mIsDrm = false; return entry; } @@ -599,6 +601,8 @@ public class MediaScanner mWriter = value.trim(); } else if (name.equalsIgnoreCase("compilation")) { mCompilation = parseSubstring(value, 0, 0); + } else if (name.equalsIgnoreCase("isdrm")) { + mIsDrm = (parseSubstring(value, 0, 0) == 1); } } @@ -671,6 +675,7 @@ public class MediaScanner map.put(MediaStore.MediaColumns.DATE_MODIFIED, mLastModified); map.put(MediaStore.MediaColumns.SIZE, mFileSize); map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType); + map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm); if (!mNoMedia) { if (MediaFile.isVideoFileType(mFileType)) { diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 8481410..9c0819f 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -487,7 +487,7 @@ public class RingtoneManager { private Cursor getInternalRingtones() { return query( MediaStore.Audio.Media.INTERNAL_CONTENT_URI, INTERNAL_COLUMNS, - constructBooleanTrueWhereClause(mFilterColumns), + constructBooleanTrueWhereClause(mFilterColumns, mIncludeDrm), null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); } @@ -506,7 +506,7 @@ public class RingtoneManager { status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) ? query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, MEDIA_COLUMNS, - constructBooleanTrueWhereClause(mFilterColumns), null, + constructBooleanTrueWhereClause(mFilterColumns, mIncludeDrm), null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER) : null; } @@ -536,11 +536,13 @@ public class RingtoneManager { * @param columns The columns that must be true. * @return The where clause. */ - private static String constructBooleanTrueWhereClause(List<String> columns) { + private static String constructBooleanTrueWhereClause(List<String> columns, boolean includeDrm) { if (columns == null) return null; StringBuilder sb = new StringBuilder(); + sb.append("("); + for (int i = columns.size() - 1; i >= 0; i--) { sb.append(columns.get(i)).append("=1 or "); } @@ -549,7 +551,18 @@ public class RingtoneManager { // Remove last ' or ' sb.setLength(sb.length() - 4); } - + + sb.append(")"); + + if (!includeDrm) { + // If not DRM files should be shown, the where clause + // will be something like "(is_notification=1) and is_drm=0" + sb.append(" and "); + sb.append(MediaStore.MediaColumns.IS_DRM); + sb.append("=0"); + } + + return sb.toString(); } diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 5582f92..73a05a5 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -387,10 +387,6 @@ status_t MPEG4Extractor::readMetaData() { return mInitCheck; } -void MPEG4Extractor::setDrmFlag(bool flag) { - mIsDrm = flag; -} - char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { if (mFirstSINF == NULL) { return NULL; diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp index af0131e..a8023df 100644 --- a/media/libstagefright/MediaExtractor.cpp +++ b/media/libstagefright/MediaExtractor.cpp @@ -116,8 +116,13 @@ sp<MediaExtractor> MediaExtractor::Create( } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) { ret = new AACExtractor(source); } - if (ret != NULL && isDrm) { - ret->getMetaData()->setInt32(kKeyIsDRM, 1); + + if (ret != NULL) { + if (isDrm) { + ret->setDrmFlag(true); + } else { + ret->setDrmFlag(false); + } } return ret; diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index f82ff32..89faff7 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -158,6 +158,7 @@ status_t StagefrightMediaScanner::processFile( { "duration", METADATA_KEY_DURATION }, { "writer", METADATA_KEY_WRITER }, { "compilation", METADATA_KEY_COMPILATION }, + { "isdrm", METADATA_KEY_IS_DRM }, }; static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]); diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index de3957b..778c0b5 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -530,6 +530,11 @@ void StagefrightMetadataRetriever::parseMetaData() { } } } + + // To check whether the media file is drm-protected + if (mExtractor->getDrmFlag()) { + mMetaData.add(METADATA_KEY_IS_DRM, String8("1")); + } } } // namespace android diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index 3bd4c7e..eae62c6 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -40,7 +40,6 @@ public: virtual sp<MetaData> getMetaData(); // for DRM - virtual void setDrmFlag(bool flag); virtual char* getDrmTrackInfo(size_t trackID, int *len); protected: diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml index e5f52e2..dd0d064 100644 --- a/packages/SettingsProvider/AndroidManifest.xml +++ b/packages/SettingsProvider/AndroidManifest.xml @@ -6,7 +6,6 @@ android:label="@string/app_label" android:process="system" android:backupAgent="SettingsBackupAgent" - android:fullBackupAgent="SettingsBackupAgent" android:killAfterRestore="false" android:icon="@drawable/ic_launcher_settings"> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 9469601..3a7a6e1 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -36,7 +36,7 @@ import java.util.zip.CRC32; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.app.backup.BackupAgentHelper; -import android.app.backup.FullBackup; +import android.app.backup.FullBackupDataOutput; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; @@ -132,58 +132,22 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); byte[] wifiConfigData = getFileData(mWifiConfigFile); - // This same agent class is used for both full and incremental backups. A full - // backup is flagged by a 'null' oldState argument. In the case of a full backup, - // the output is structured as tarfile contents. - if (oldState != null) { - long[] stateChecksums = readOldChecksums(oldState); - - stateChecksums[STATE_SYSTEM] = - writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data); - stateChecksums[STATE_SECURE] = - writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data); - stateChecksums[STATE_LOCALE] = - writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); - stateChecksums[STATE_WIFI_SUPPLICANT] = - writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT, - wifiSupplicantData, data); - stateChecksums[STATE_WIFI_CONFIG] = - writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData, - data); - - writeNewChecksums(stateChecksums, newState); - } else { - // Write the data to the staging file, then emit that as our tarfile - // representation of the backed-up settings. - String root = getFilesDir().getAbsolutePath(); - File stage = new File(root, STAGE_FILE); - try { - FileOutputStream filestream = new FileOutputStream(stage); - BufferedOutputStream bufstream = new BufferedOutputStream(filestream); - DataOutputStream out = new DataOutputStream(bufstream); - - out.writeInt(FULL_BACKUP_VERSION); - - out.writeInt(systemSettingsData.length); - out.write(systemSettingsData); - out.writeInt(secureSettingsData.length); - out.write(secureSettingsData); - out.writeInt(locale.length); - out.write(locale); - out.writeInt(wifiSupplicantData.length); - out.write(wifiSupplicantData); - out.writeInt(wifiConfigData.length); - out.write(wifiConfigData); - - out.flush(); // also flushes downstream - - // now we're set to emit the tar stream - FullBackup.backupToTar(getPackageName(), FullBackup.DATA_TREE_TOKEN, null, - root, stage.getAbsolutePath(), data); - } finally { - stage.delete(); - } - } + long[] stateChecksums = readOldChecksums(oldState); + + stateChecksums[STATE_SYSTEM] = + writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data); + stateChecksums[STATE_SECURE] = + writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data); + stateChecksums[STATE_LOCALE] = + writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); + stateChecksums[STATE_WIFI_SUPPLICANT] = + writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT, + wifiSupplicantData, data); + stateChecksums[STATE_WIFI_CONFIG] = + writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData, + data); + + writeNewChecksums(stateChecksums, newState); } @Override @@ -221,6 +185,45 @@ public class SettingsBackupAgent extends BackupAgentHelper { } @Override + public void onFullBackup(FullBackupDataOutput data) throws IOException { + byte[] systemSettingsData = getSystemSettings(); + byte[] secureSettingsData = getSecureSettings(); + byte[] locale = mSettingsHelper.getLocaleData(); + byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); + byte[] wifiConfigData = getFileData(mWifiConfigFile); + + // Write the data to the staging file, then emit that as our tarfile + // representation of the backed-up settings. + String root = getFilesDir().getAbsolutePath(); + File stage = new File(root, STAGE_FILE); + try { + FileOutputStream filestream = new FileOutputStream(stage); + BufferedOutputStream bufstream = new BufferedOutputStream(filestream); + DataOutputStream out = new DataOutputStream(bufstream); + + out.writeInt(FULL_BACKUP_VERSION); + + out.writeInt(systemSettingsData.length); + out.write(systemSettingsData); + out.writeInt(secureSettingsData.length); + out.write(secureSettingsData); + out.writeInt(locale.length); + out.write(locale); + out.writeInt(wifiSupplicantData.length); + out.write(wifiSupplicantData); + out.writeInt(wifiConfigData.length); + out.write(wifiConfigData); + + out.flush(); // also flushes downstream + + // now we're set to emit the tar stream + fullBackupFile(stage, data); + } finally { + stage.delete(); + } + } + + @Override public void onRestoreFile(ParcelFileDescriptor data, long size, int type, String domain, String relpath, long mode, long mtime) throws IOException { diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml index 258059c..39c36f1 100644 --- a/packages/SharedStorageBackup/AndroidManifest.xml +++ b/packages/SharedStorageBackup/AndroidManifest.xml @@ -23,7 +23,7 @@ <application android:allowClearUserData="false" android:permission="android.permission.CONFIRM_FULL_BACKUP" - android:fullBackupAgent=".SharedStorageAgent" + android:backupAgent=".SharedStorageAgent" android:allowBackup="false" > </application> </manifest> diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java index b02ca2e..6c677b8 100644 --- a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java +++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java @@ -1,9 +1,10 @@ package com.android.sharedstoragebackup; -import android.app.backup.FullBackup; import android.app.backup.FullBackupAgent; +import android.app.backup.FullBackup; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; +import android.app.backup.FullBackupDataOutput; import android.content.Context; import android.os.Environment; import android.os.ParcelFileDescriptor; @@ -30,9 +31,11 @@ public class SharedStorageAgent extends FullBackupAgent { } } + /** + * Full backup of the shared-storage filesystem + */ @Override - public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) throws IOException { + public void onFullBackup(FullBackupDataOutput output) throws IOException { // If there are shared-storage volumes available, run the inherited directory- // hierarchy backup process on them. By convention in the Storage Manager, the // "primary" shared storage volume is first in the list. @@ -43,20 +46,12 @@ public class SharedStorageAgent extends FullBackupAgent { // shared/N/path/to/file // The restore will then extract to the given volume String domain = FullBackup.SHARED_PREFIX + i; - processTree(null, domain, v.getPath(), null, data); + fullBackupFileTree(null, domain, v.getPath(), null, output); } } } /** - * Incremental onRestore() implementation is not used. - */ - @Override - public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) - throws IOException { - } - - /** * Full restore of one file to shared storage */ @Override @@ -88,6 +83,6 @@ public class SharedStorageAgent extends FullBackupAgent { Slog.e(TAG, "Skipping data with malformed path " + relpath); } - FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, false); + FullBackup.restoreFile(data, size, type, -1, mtime, outFile); } } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index f42cbbf..26ea225 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -30,10 +30,6 @@ <service android:name=".screenshot.TakeScreenshotService" android:exported="false" /> - <activity android:name=".usb.UsbPreferenceActivity" - android:theme="@*android:style/Theme.Holo.Dialog.Alert" - android:excludeFromRecents="true"> - </activity> <activity android:name=".usb.UsbStorageActivity" android:excludeFromRecents="true"> </activity> diff --git a/packages/SystemUI/res/layout/usb_preference_buttons.xml b/packages/SystemUI/res/layout/usb_preference_buttons.xml deleted file mode 100644 index babe07e..0000000 --- a/packages/SystemUI/res/layout/usb_preference_buttons.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<!-- Check box that is displayed in the activity resolver UI for the user - to make their selection the preferred activity. --> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingLeft="14dip" - android:paddingRight="15dip" - android:orientation="vertical"> - - <Button - android:id="@+id/mtp_ptp_button" - android:text="@string/use_ptp_button_title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:focusable="true" - android:clickable="true" /> - - <Button - android:id="@+id/installer_cd_button" - android:text="@string/installer_cd_button_title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:focusable="true" - android:clickable="true" /> - -</LinearLayout> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 70f9b75..882455e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -157,15 +157,6 @@ <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] --> <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string> - <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] --> - <string name="usb_preference_title">USB file transfer options</string> - <!-- Label for the MTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] --> - <string name="use_mtp_button_title">Mount as a media player (MTP)</string> - <!-- Label for the PTP USB function in UsbPreferenceActivity. [CHAR LIMIT=50] --> - <string name="use_ptp_button_title">Mount as a camera (PTP)</string> - <!-- Label for the installer CD image option in UsbPreferenceActivity. [CHAR LIMIT=50] --> - <string name="installer_cd_button_title">Install Android File Transfer application for Mac</string> - <!-- 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. --> diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java deleted file mode 100644 index 60906a1..0000000 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbPreferenceActivity.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.usb; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.hardware.usb.UsbManager; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.util.Log; -import android.widget.Button; - -import java.io.File; - -import com.android.systemui.R; - -public class UsbPreferenceActivity extends Activity implements View.OnClickListener { - - private static final String TAG = "UsbPreferenceActivity"; - - private UsbManager mUsbManager; - private String mCurrentFunction; - private String[] mFunctions; - private String mInstallerImagePath; - private AlertDialog mDialog; - private Button mMtpPtpButton; - private Button mInstallerCdButton; - private boolean mPtpActive; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE); - - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); - dialogBuilder.setTitle(getString(R.string.usb_preference_title)); - - LayoutInflater inflater = (LayoutInflater)getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - View buttonView = inflater.inflate(R.layout.usb_preference_buttons, null); - dialogBuilder.setView(buttonView); - mMtpPtpButton = (Button)buttonView.findViewById(R.id.mtp_ptp_button); - mInstallerCdButton = (Button)buttonView.findViewById(R.id.installer_cd_button); - mMtpPtpButton.setOnClickListener(this); - mInstallerCdButton.setOnClickListener(this); - - mPtpActive = mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP); - if (mPtpActive) { - mMtpPtpButton.setText(R.string.use_mtp_button_title); - } - - mInstallerImagePath = getString(com.android.internal.R.string.config_isoImagePath); - if (!(new File(mInstallerImagePath)).exists()) { - mInstallerCdButton.setVisibility(View.GONE); - } - - mDialog = dialogBuilder.show(); - } - - public void onClick(View v) { - if (v.equals(mMtpPtpButton)) { - if (mPtpActive) { - mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true); - } else { - mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true); - } - } else if (v.equals(mInstallerCdButton)) { - // installer CD is never default - mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MASS_STORAGE, false); - mUsbManager.setMassStorageBackingFile(mInstallerImagePath); - } - - if (mDialog != null) { - mDialog.dismiss(); - } - finish();
- } -} diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 3aa1239..6afccec 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -23,6 +23,7 @@ import android.app.IActivityManager; import android.app.IApplicationThread; import android.app.IBackupAgent; import android.app.PendingIntent; +import android.app.backup.BackupAgent; import android.app.backup.BackupDataOutput; import android.app.backup.FullBackup; import android.app.backup.RestoreSet; @@ -64,6 +65,7 @@ import android.os.SystemClock; import android.os.WorkSource; import android.provider.Settings; import android.util.EventLog; +import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; @@ -1587,8 +1589,7 @@ class BackupManagerService extends IBackupManager.Stub { // Initiate the target's backup pass prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL); - agent.doBackup(savedState, backupData, newState, false, - token, mBackupManagerBinder); + agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder); boolean success = waitUntilOperationComplete(token); if (!success) { @@ -1764,30 +1765,31 @@ class BackupManagerService extends IBackupManager.Stub { if (agent != null) { try { ApplicationInfo app = pkg.applicationInfo; - boolean sendApk = mIncludeApks + final boolean sendApk = mIncludeApks && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0) && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 || (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); sendOnBackupPackage(pkg.packageName); - { - BackupDataOutput output = new BackupDataOutput( - mOutputFile.getFileDescriptor()); + BackupDataOutput output = new BackupDataOutput( + mOutputFile.getFileDescriptor()); - if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); - writeAppManifest(pkg, mManifestFile, sendApk); - FullBackup.backupToTar(pkg.packageName, null, null, - mFilesDir.getAbsolutePath(), - mManifestFile.getAbsolutePath(), - output); + if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); + writeAppManifest(pkg, mManifestFile, sendApk); + FullBackup.backupToTar(pkg.packageName, null, null, + mFilesDir.getAbsolutePath(), + mManifestFile.getAbsolutePath(), + output); + + if (sendApk) { + writeApkToBackup(pkg, output); } - if (DEBUG) Slog.d(TAG, "Calling doBackup()"); + if (DEBUG) Slog.d(TAG, "Calling doFullBackup()"); final int token = generateToken(); prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL); - agent.doBackup(null, mOutputFile, null, sendApk, - token, mBackupManagerBinder); + agent.doFullBackup(mOutputFile, token, mBackupManagerBinder); if (!waitUntilOperationComplete(token)) { Slog.e(TAG, "Full backup failed on package " + pkg.packageName); } else { @@ -1802,6 +1804,29 @@ class BackupManagerService extends IBackupManager.Stub { tearDown(pkg); } + private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) { + // Forward-locked apps, system-bundled .apks, etc are filtered out before we get here + final String appSourceDir = pkg.applicationInfo.sourceDir; + final String apkDir = new File(appSourceDir).getParent(); + FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null, + apkDir, appSourceDir, output); + + // Save associated .obb content if it exists and we did save the apk + // check for .obb and save those too + final File obbDir = Environment.getExternalStorageAppObbDirectory(pkg.packageName); + if (obbDir != null) { + if (DEBUG) Log.i(TAG, "obb dir: " + obbDir.getAbsolutePath()); + File[] obbFiles = obbDir.listFiles(); + if (obbFiles != null) { + final String obbDirName = obbDir.getAbsolutePath(); + for (File obb : obbFiles) { + FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null, + obbDirName, obb.getAbsolutePath(), output); + } + } + } + } + private void backupSharedStorage() throws RemoteException { PackageInfo pkg = null; try { @@ -1813,7 +1838,7 @@ class BackupManagerService extends IBackupManager.Stub { final int token = generateToken(); prepareOperationTimeout(token, TIMEOUT_SHARED_BACKUP_INTERVAL); - agent.doBackup(null, mOutputFile, null, false, token, mBackupManagerBinder); + agent.doFullBackup(mOutputFile, token, mBackupManagerBinder); if (!waitUntilOperationComplete(token)) { Slog.e(TAG, "Full backup failed on shared storage"); } else { @@ -1933,7 +1958,7 @@ class BackupManagerService extends IBackupManager.Stub { static class FileMetadata { String packageName; // name of the owning app String installerPackageName; // name of the market-type app that installed the owner - int type; // e.g. FullBackup.TYPE_DIRECTORY + int type; // e.g. BackupAgent.TYPE_DIRECTORY String domain; // e.g. FullBackup.DATABASE_TREE_TOKEN String path; // subpath within the semantic domain long mode; // e.g. 0666 (actually int) @@ -2182,15 +2207,15 @@ class BackupManagerService extends IBackupManager.Stub { // If we haven't sent any data to this app yet, we probably // need to clear it first. Check that. if (!mClearedPackages.contains(pkg)) { - // apps with their own full backup agents are + // apps with their own backup agents are // responsible for coherently managing a full // restore. - if (mTargetApp.fullBackupAgentName == null) { + if (mTargetApp.backupAgentName == null) { if (DEBUG) Slog.d(TAG, "Clearing app data preparatory to full restore"); clearApplicationDataSynchronous(pkg); } else { - if (DEBUG) Slog.d(TAG, "full backup agent (" - + mTargetApp.fullBackupAgentName + ") => no clear"); + if (DEBUG) Slog.d(TAG, "backup agent (" + + mTargetApp.backupAgentName + ") => no clear"); } mClearedPackages.add(pkg); } else { @@ -2686,7 +2711,7 @@ class BackupManagerService extends IBackupManager.Stub { StringBuilder b = new StringBuilder(128); // mode string - b.append((info.type == FullBackup.TYPE_DIRECTORY) ? 'd' : '-'); + b.append((info.type == BackupAgent.TYPE_DIRECTORY) ? 'd' : '-'); b.append(((info.mode & 0400) != 0) ? 'r' : '-'); b.append(((info.mode & 0200) != 0) ? 'w' : '-'); b.append(((info.mode & 0100) != 0) ? 'x' : '-'); @@ -2746,9 +2771,9 @@ class BackupManagerService extends IBackupManager.Stub { } switch (typeChar) { - case '0': info.type = FullBackup.TYPE_FILE; break; + case '0': info.type = BackupAgent.TYPE_FILE; break; case '5': { - info.type = FullBackup.TYPE_DIRECTORY; + info.type = BackupAgent.TYPE_DIRECTORY; if (info.size != 0) { Slog.w(TAG, "Directory entry with nonzero size in header"); info.size = 0; diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index afc04bb..b98d2a2 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -64,6 +64,7 @@ import android.util.EventLog; import android.util.Slog; import android.util.SparseIntArray; +import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.telephony.Phone; import com.android.server.connectivity.Tethering; @@ -2469,8 +2470,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { /** * Protect a socket from VPN routing rules. This method is used by - * VpnBuilder and not available in ConnectivityManager. Permission - * checks are done in Vpn class. + * VpnBuilder and not available in ConnectivityManager. Permissions + * are checked in Vpn class. * @hide */ @Override @@ -2480,8 +2481,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { /** * Prepare for a VPN application. This method is used by VpnDialogs - * and not available in ConnectivityManager. Permission checks are - * done in Vpn class. + * and not available in ConnectivityManager. Permissions are checked + * in Vpn class. * @hide */ @Override @@ -2492,8 +2493,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { /** * Configure a TUN interface and return its file descriptor. Parameters * are encoded and opaque to this class. This method is used by VpnBuilder - * and not available in ConnectivityManager. Permission checks are done - * in Vpn class. + * and not available in ConnectivityManager. Permissions are checked in + * Vpn class. * @hide */ @Override @@ -2502,12 +2503,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { } /** - * Handle a legacy VPN request. + * Start legacy VPN and return an intent to VpnDialogs. This method is + * used by VpnSettings and not available in ConnectivityManager. + * Permissions are checked in Vpn class. + * @hide + */ + @Override + public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { + mVpn.startLegacyVpn(config, racoon, mtpd); + } + + /** + * Return the information of the ongoing legacy VPN. This method is used + * by VpnSettings and not available in ConnectivityManager. Permissions + * are checked in Vpn class. * @hide */ @Override - public void doLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { - mVpn.doLegacyVpn(config, racoon, mtpd); + public LegacyVpnInfo getLegacyVpnInfo() { + return mVpn.getLegacyVpnInfo(); } private String getDefaultInterface() { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 14abf80..2d55433 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1623,8 +1623,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (lastImi == null) return null; try { final int lastSubtypeHash = Integer.valueOf(lastIme.second); - return lastImi.getSubtypeAt(getSubtypeIdFromHashCode( - lastImi, lastSubtypeHash)); + final int lastSubtypeId = getSubtypeIdFromHashCode(lastImi, lastSubtypeHash); + if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) { + return null; + } + return lastImi.getSubtypeAt(lastSubtypeId); } catch (NumberFormatException e) { return null; } diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java index 08c6699..950f3b6 100644 --- a/services/java/com/android/server/SystemBackupAgent.java +++ b/services/java/com/android/server/SystemBackupAgent.java @@ -138,7 +138,7 @@ public class SystemBackupAgent extends BackupAgentHelper { if (outFile == null) { Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]"); } - FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true); + FullBackup.restoreFile(data, size, type, mode, mtime, outFile); if (restoredWallpaper) { WallpaperManagerService wallpaper = diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 7725891..5f0922e 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -36,6 +36,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiStateMachine; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiWatchdogService; import android.net.wifi.WpsConfiguration; import android.net.wifi.WpsResult; import android.net.ConnectivityManager; diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index 10dd924..80cdf6b 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -436,7 +436,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub public IAccessibilityServiceConnection registerEventListener(IEventListener listener) { mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT, FUNCTION_REGISTER_EVENT_LISTENER); - ComponentName componentName = new ComponentName("foo.bar", "FakeAccessibilityService"); + ComponentName componentName = new ComponentName("foo.bar", + "AutomationAccessibilityService"); synchronized (mLock) { Service oldService = mComponentNameToServiceMap.get(componentName); if (oldService != null) { @@ -829,7 +830,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub boolean mCanRetrieveScreenContent; - boolean mIsFake; + boolean mIsAutomation; final Callback mCallback = new Callback(); @@ -842,12 +843,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub new SparseArray<AccessibilityEvent>(); public Service(ComponentName componentName, - AccessibilityServiceInfo accessibilityServiceInfo, boolean isFake) { + AccessibilityServiceInfo accessibilityServiceInfo, boolean isAutomation) { mId = sIdCounter++; mComponentName = componentName; mAccessibilityServiceInfo = accessibilityServiceInfo; - mIsFake = isFake; - if (!isFake) { + mIsAutomation = isAutomation; + if (!isAutomation) { mCanRetrieveScreenContent = accessibilityServiceInfo.getCanRetrieveWindowContent(); mIntent = new Intent().setComponent(mComponentName); mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL, @@ -881,7 +882,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * @return True if binding is successful. */ public boolean bind() { - if (!mIsFake && mService == null) { + if (!mIsAutomation && mService == null) { return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE); } return false; @@ -898,7 +899,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub synchronized (mLock) { tryRemoveServiceLocked(this); } - if (!mIsFake) { + if (!mIsAutomation) { mContext.unbindService(this); } mService = null; @@ -938,16 +939,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub IAccessibilityInteractionConnection connection = null; synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this); - if (permissionGranted) { + if (!permissionGranted) { + return null; + } else { connection = getConnectionToRetrievalAllowingWindowLocked(); + if (connection == null) { + if (DEBUG) { + Slog.e(LOG_TAG, "No interaction connection to a retrieve " + + "allowing window."); + } + return null; + } } } - if (connection == null) { - if (DEBUG) { - Slog.e(LOG_TAG, "No interaction connection to a retrieve allowing window."); - } - return null; - } final long identityToken = Binder.clearCallingIdentity(); try { final int interactionId = mInteractionIdCounter.getAndIncrement(); @@ -982,16 +986,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); - if (permissionGranted) { + if (!permissionGranted) { + return null; + } else { connection = getConnectionToRetrievalAllowingWindowLocked(); + if (connection == null) { + if (DEBUG) { + Slog.e(LOG_TAG, "No interaction connection to focused window."); + } + return null; + } } } - if (connection == null) { - if (DEBUG) { - Slog.e(LOG_TAG, "No interaction connection to focused window."); - } - return null; - } final long identityToken = Binder.clearCallingIdentity(); try { final int interactionId = mInteractionIdCounter.getAndIncrement(); @@ -1025,17 +1031,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); - if (permissionGranted) { + if (!permissionGranted) { + return null; + } else { connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId); + if (connection == null) { + if (DEBUG) { + Slog.e(LOG_TAG, "No interaction connection to window: " + + accessibilityWindowId); + } + return null; + } } } - if (connection == null) { - if (DEBUG) { - Slog.e(LOG_TAG, "No interaction connection to window: " - + accessibilityWindowId); - } - return null; - } final long identityToken = Binder.clearCallingIdentity(); try { final int interactionId = mInteractionIdCounter.getAndIncrement(); @@ -1066,17 +1074,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this, accessibilityWindowId, action); - if (permissionGranted) { + if (!permissionGranted) { + return false; + } else { connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId); + if (connection == null) { + if (DEBUG) { + Slog.e(LOG_TAG, "No interaction connection to window: " + + accessibilityWindowId); + } + return false; + } } } - if (connection == null) { - if (DEBUG) { - Slog.e(LOG_TAG, "No interaction connection to window: " - + accessibilityWindowId); - } - return false; - } final long identityToken = Binder.clearCallingIdentity(); try { final int interactionId = mInteractionIdCounter.getAndIncrement(); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 48b0b66..29cccb6 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1953,6 +1953,9 @@ public final class ActivityManagerService extends ActivityManagerNative if ("1".equals(SystemProperties.get("debug.checkjni"))) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } + if ("1".equals(SystemProperties.get("debug.jni.logging"))) { + debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; + } if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index bb3ce28..c185012 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -37,6 +37,7 @@ import android.os.SystemProperties; import android.util.Log; import com.android.internal.R; +import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.server.ConnectivityService.VpnCallback; @@ -250,6 +251,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mContext.getString(R.string.vpn_title_long, label); String text = (config.session == null) ? mContext.getString(R.string.vpn_text) : mContext.getString(R.string.vpn_text_long, config.session); + config.startTime = SystemClock.elapsedRealtime(); long identity = Binder.clearCallingIdentity(); Notification notification = new Notification.Builder(mContext) @@ -257,7 +259,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { .setLargeIcon(icon) .setContentTitle(title) .setContentText(text) - .setContentIntent(VpnConfig.getIntentForNotification(mContext, config)) + .setContentIntent(VpnConfig.getIntentForStatusPanel(mContext, config)) .setDefaults(Notification.DEFAULT_ALL) .setOngoing(true) .getNotification(); @@ -284,24 +286,35 @@ public class Vpn extends INetworkManagementEventObserver.Stub { private native void jniProtect(int socket, String interfaze); /** - * Handle a legacy VPN request. This method stops the daemons and restart - * them if arguments are not null. Heavy things are offloaded to another + * Start legacy VPN. This method stops the daemons and restart them + * if arguments are not null. Heavy things are offloaded to another * thread, so callers will not be blocked for a long time. * * @param config The parameters to configure the network. * @param raoocn The arguments to be passed to racoon. * @param mtpd The arguments to be passed to mtpd. */ - public synchronized void doLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { + public synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { // Prepare for the new request. This also checks the caller. prepare(null, VpnConfig.LEGACY_VPN); - // Start a new runner and we are done! + // Start a new LegacyVpnRunner and we are done! mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); mLegacyVpnRunner.start(); } /** + * Return the information of the current ongoing legacy VPN. + */ + public synchronized LegacyVpnInfo getLegacyVpnInfo() { + // Only system user can call this method. + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Unauthorized Caller"); + } + return (mLegacyVpnRunner == null) ? null : mLegacyVpnRunner.getInfo(); + } + + /** * Bringing up a VPN connection takes time, and that is all this thread * does. Here we have plenty of time. The only thing we need to take * care of is responding to interruptions as soon as possible. Otherwise @@ -315,6 +328,8 @@ public class Vpn extends INetworkManagementEventObserver.Stub { private final VpnConfig mConfig; private final String[] mDaemons; private final String[][] mArguments; + private final LegacyVpnInfo mInfo; + private long mTimer = -1; public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) { @@ -322,7 +337,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mConfig = config; mDaemons = new String[] {"racoon", "mtpd"}; mArguments = new String[][] {racoon, mtpd}; + mInfo = new LegacyVpnInfo(); + // Legacy VPN is not a real package, so we use it to carry the key. + mInfo.key = mConfig.packagz; mConfig.packagz = VpnConfig.LEGACY_VPN; } @@ -334,14 +352,22 @@ public class Vpn extends INetworkManagementEventObserver.Stub { interrupt(); } + public LegacyVpnInfo getInfo() { + // Update the info when VPN is disconnected. + if (mInfo.state == LegacyVpnInfo.STATE_CONNECTED && mInterface == null) { + mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED; + mInfo.intent = null; + } + return mInfo; + } + @Override public void run() { // Wait for the previous thread since it has been interrupted. - Log.v(TAG, "wait"); + Log.v(TAG, "Waiting"); synchronized (TAG) { - Log.v(TAG, "begin"); + Log.v(TAG, "Executing"); execute(); - Log.v(TAG, "end"); } } @@ -353,7 +379,8 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } else if (now - mTimer <= 30000) { Thread.sleep(yield ? 200 : 1); } else { - throw new InterruptedException("time is up"); + mInfo.state = LegacyVpnInfo.STATE_TIMEOUT; + throw new IllegalStateException("time is up"); } } @@ -362,6 +389,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { try { // Initialize the timer. checkpoint(false); + mInfo.state = LegacyVpnInfo.STATE_INITIALIZING; // First stop the daemons. for (String daemon : mDaemons) { @@ -390,8 +418,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { restart = restart || (arguments != null); } if (!restart) { + mInfo.state = LegacyVpnInfo.STATE_DISCONNECTED; return; } + mInfo.state = LegacyVpnInfo.STATE_CONNECTING; // Start the daemon with arguments. for (int i = 0; i < mDaemons.length; ++i) { @@ -459,7 +489,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { String daemon = mDaemons[i]; if (mArguments[i] != null && !"running".equals( SystemProperties.get("init.svc." + daemon))) { - throw new IllegalArgumentException(daemon + " is dead"); + throw new IllegalStateException(daemon + " is dead"); } } checkpoint(true); @@ -492,11 +522,20 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mInterface = mConfig.interfaze; mCallback.override(mConfig.dnsServers, mConfig.searchDomains); showNotification(mConfig, null, null); + + Log.i(TAG, "Connected!"); + mInfo.state = LegacyVpnInfo.STATE_CONNECTED; + mInfo.intent = VpnConfig.getIntentForStatusPanel(mContext, null); } - Log.i(TAG, "Connected!"); } catch (Exception e) { - Log.i(TAG, "Abort because " + e.getMessage()); + Log.i(TAG, "Aborting", e); exit(); + } finally { + // Do not leave an unstable state. + if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING || + mInfo.state == LegacyVpnInfo.STATE_CONNECTING) { + mInfo.state = LegacyVpnInfo.STATE_FAILED; + } } } } diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index 13a76b3..d645160 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -72,7 +72,9 @@ public class UsbDeviceManager { private static final String STATE_PATH = "/sys/class/android_usb/android0/state"; private static final String MASS_STORAGE_FILE_PATH = - "/sys/class/android_usb/f_mass_storage/lun/file"; + "/sys/class/android_usb/android0/f_mass_storage/lun/file"; + private static final String RNDIS_ETH_ADDR_PATH = + "/sys/class/android_usb/android0/f_rndis/ethaddr"; private static final int MSG_UPDATE_STATE = 0; private static final int MSG_ENABLE_ADB = 1; @@ -132,6 +134,7 @@ public class UsbDeviceManager { mSettingsManager = settingsManager; PackageManager pm = mContext.getPackageManager(); mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); + initRndisAddress(); // create a thread for our Handler HandlerThread thread = new HandlerThread("UsbDeviceManager", @@ -166,6 +169,29 @@ public class UsbDeviceManager { mHandler.sendEmptyMessage(MSG_SYSTEM_READY); } + private static void initRndisAddress() { + // configure RNDIS ethernet address based on our serial number using the same algorithm + // we had been previously using in kernel board files + final int ETH_ALEN = 6; + int address[] = new int[ETH_ALEN]; + // first byte is 0x02 to signify a locally administered address + address[0] = 0x02; + + String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF"); + int serialLength = serial.length(); + // XOR the USB serial across the remaining 5 bytes + for (int i = 0; i < serialLength; i++) { + address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i); + } + String addrString = String.format("%02X:%02X:%02X:%02X:%02X:%02X", + address[0], address[1], address[2], address[3], address[4], address[5]); + try { + FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString); + } catch (IOException e) { + Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH); + } + } + private static String addFunction(String functions, String function) { if (!containsFunction(functions, function)) { if (functions.length() > 0) { @@ -530,11 +556,12 @@ public class UsbDeviceManager { notification.sound = null; notification.vibrate = null; - Intent intent = new Intent(); + Intent intent = new Intent( + Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - intent.setClassName("com.android.systemui", - "com.android.systemui.usb.UsbPreferenceActivity"); + intent.setComponent(new ComponentName("com.android.settings", + "com.android.settings.UsbSettings")); PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); notification.setLatestEventInfo(mContext, title, message, pi); diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp index a774841..33125c4 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -103,6 +103,11 @@ void DisplayHardware::init(uint32_t dpy) { mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); + if (!fbDev) { + LOGE("Display subsystem failed to initialize. check logs. exiting..."); + exit(0); + } + mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 685613e..cccab4a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -163,9 +163,34 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); mBootFinished = true; + + // wait patiently for the window manager death + const String16 name("window"); + sp<IBinder> window(defaultServiceManager()->getService(name)); + if (window != 0) { + window->linkToDeath(this); + } + + // stop boot animation property_set("ctl.stop", "bootanim"); } +void SurfaceFlinger::binderDied(const wp<IBinder>& who) +{ + // the window manager died on us. prepare its eulogy. + + // unfreeze the screen in case it was... frozen + mFreezeDisplayTime = 0; + mFreezeCount = 0; + mFreezeDisplay = false; + + // reset screen orientation + setOrientation(0, eOrientationDefault, 0); + + // restart the boot-animation + property_set("ctl.start", "bootanim"); +} + void SurfaceFlinger::onFirstRef() { run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); @@ -2470,11 +2495,14 @@ GraphicBufferAlloc::GraphicBufferAlloc() {} GraphicBufferAlloc::~GraphicBufferAlloc() {} sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage) { + PixelFormat format, uint32_t usage, status_t* error) { sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); status_t err = graphicBuffer->initCheck(); + *error = err; if (err != 0 || graphicBuffer->handle == 0) { - GraphicBuffer::dumpAllocationsToSystemLog(); + if (err == NO_MEMORY) { + GraphicBuffer::dumpAllocationsToSystemLog(); + } LOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " "failed (%s), handle=%p", w, h, strerror(-err), graphicBuffer->handle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b49fa36..15661f0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -96,7 +96,7 @@ public: GraphicBufferAlloc(); virtual ~GraphicBufferAlloc(); virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage); + PixelFormat format, uint32_t usage, status_t* error); }; // --------------------------------------------------------------------------- @@ -147,6 +147,7 @@ enum { class SurfaceFlinger : public BinderService<SurfaceFlinger>, public BnSurfaceComposer, + public IBinder::DeathRecipient, protected Thread { public: @@ -193,6 +194,10 @@ public: sp<Layer> getLayer(const sp<ISurface>& sur) const; private: + // DeathRecipient interface + virtual void binderDied(const wp<IBinder>& who); + +private: friend class Client; friend class LayerBase; friend class LayerBaseClient; diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java index ddc8031..c553947 100644 --- a/voip/java/com/android/server/sip/SipService.java +++ b/voip/java/com/android/server/sip/SipService.java @@ -74,6 +74,7 @@ public final class SipService extends ISipService.Stub { private static final int SHORT_EXPIRY_TIME = 10; private static final int MIN_EXPIRY_TIME = 60; private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds + private static final int DEFAULT_MAX_KEEPALIVE_INTERVAL = 120; // in seconds private Context mContext; private String mLocalIp; @@ -101,6 +102,7 @@ public final class SipService extends ISipService.Stub { private boolean mWifiEnabled; private SipWakeLock mMyWakeLock; private int mKeepAliveInterval; + private int mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; /** * Starts the SIP service. Do nothing if the SIP API is not supported on the @@ -448,6 +450,7 @@ public final class SipService extends ISipService.Stub { if (connected) { mLocalIp = determineLocalIp(); mKeepAliveInterval = -1; + mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; for (SipSessionGroupExt group : mSipGroups.values()) { group.onConnectivityChanged(true); } @@ -471,7 +474,8 @@ public final class SipService extends ISipService.Stub { private void startPortMappingLifetimeMeasurement( SipProfile localProfile) { - startPortMappingLifetimeMeasurement(localProfile, -1); + startPortMappingLifetimeMeasurement(localProfile, + DEFAULT_MAX_KEEPALIVE_INTERVAL); } private void startPortMappingLifetimeMeasurement( @@ -482,8 +486,16 @@ public final class SipService extends ISipService.Stub { Log.d(TAG, "start NAT port mapping timeout measurement on " + localProfile.getUriString()); - mIntervalMeasurementProcess = - new IntervalMeasurementProcess(localProfile, maxInterval); + int minInterval = mLastGoodKeepAliveInterval; + if (minInterval >= maxInterval) { + // If mLastGoodKeepAliveInterval also does not work, reset it + // to the default min + minInterval = mLastGoodKeepAliveInterval + = DEFAULT_KEEPALIVE_INTERVAL; + Log.d(TAG, " reset min interval to " + minInterval); + } + mIntervalMeasurementProcess = new IntervalMeasurementProcess( + localProfile, minInterval, maxInterval); mIntervalMeasurementProcess.start(); } } @@ -539,7 +551,7 @@ public final class SipService extends ISipService.Stub { private int getKeepAliveInterval() { return (mKeepAliveInterval < 0) - ? DEFAULT_KEEPALIVE_INTERVAL + ? mLastGoodKeepAliveInterval : mKeepAliveInterval; } @@ -768,27 +780,33 @@ public final class SipService extends ISipService.Stub { private class IntervalMeasurementProcess implements Runnable, SipSessionGroup.KeepAliveProcessCallback { private static final String TAG = "SipKeepAliveInterval"; - private static final int MAX_INTERVAL = 120; // in seconds private static final int MIN_INTERVAL = 5; // in seconds private static final int PASS_THRESHOLD = 10; private static final int MAX_RETRY_COUNT = 5; private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds private SipSessionGroupExt mGroup; private SipSessionGroup.SipSessionImpl mSession; - private int mMinInterval = DEFAULT_KEEPALIVE_INTERVAL; // in seconds + private int mMinInterval; private int mMaxInterval; private int mInterval; private int mPassCount = 0; - public IntervalMeasurementProcess(SipProfile localProfile, int maxInterval) { - mMaxInterval = (maxInterval < 0) ? MAX_INTERVAL : maxInterval; - mInterval = (mMaxInterval + mMinInterval) / 2; + public IntervalMeasurementProcess(SipProfile localProfile, + int minInterval, int maxInterval) { + mMaxInterval = maxInterval; + mMinInterval = minInterval; + mInterval = (maxInterval + minInterval) / 2; // Don't start measurement if the interval is too small - if (mInterval < MIN_INTERVAL) { + if (mInterval < DEFAULT_KEEPALIVE_INTERVAL) { Log.w(TAG, "interval is too small; measurement aborted; " + "maxInterval=" + mMaxInterval); return; + } else if (checkTermination()) { + Log.w(TAG, "interval is too small; measurement aborted; " + + "interval=[" + mMinInterval + "," + mMaxInterval + + "]"); + return; } try { @@ -842,6 +860,10 @@ public final class SipService extends ISipService.Stub { } } + private boolean checkTermination() { + return ((mMaxInterval - mMinInterval) < MIN_INTERVAL); + } + // SipSessionGroup.KeepAliveProcessCallback @Override public void onResponse(boolean portChanged) { @@ -850,6 +872,9 @@ public final class SipService extends ISipService.Stub { if (++mPassCount != PASS_THRESHOLD) return; // update the interval, since the current interval is good to // keep the port mapping. + if (mKeepAliveInterval > 0) { + mLastGoodKeepAliveInterval = mKeepAliveInterval; + } mKeepAliveInterval = mMinInterval = mInterval; if (DEBUG) { Log.d(TAG, "measured good keepalive interval: " @@ -860,9 +885,13 @@ public final class SipService extends ISipService.Stub { // Since the rport is changed, shorten the interval. mMaxInterval = mInterval; } - if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) { + if (checkTermination()) { // update mKeepAliveInterval and stop measurement. stop(); + // If all the measurements failed, we still set it to + // mMinInterval; If mMinInterval still doesn't work, a new + // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL + // will be conducted. mKeepAliveInterval = mMinInterval; if (DEBUG) { Log.d(TAG, "measured keepalive interval: " diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 2a033d1..8c28319 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -2085,9 +2085,9 @@ public class WifiStateMachine extends StateMachine { transitionTo(mDriverLoadedState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); } else { - mSupplicantRestartCount = 0; Log.e(TAG, "Failed " + mSupplicantRestartCount + " times to start supplicant, unload driver"); + mSupplicantRestartCount = 0; transitionTo(mDriverLoadedState); sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); } diff --git a/services/java/com/android/server/WifiWatchdogService.java b/wifi/java/android/net/wifi/WifiWatchdogService.java index 1356e2a..bce4b3a 100644 --- a/services/java/com/android/server/WifiWatchdogService.java +++ b/wifi/java/android/net/wifi/WifiWatchdogService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package android.net.wifi; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -23,12 +23,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.net.ConnectivityManager; +import android.net.DnsPinger; import android.net.NetworkInfo; import android.net.Uri; -import android.net.wifi.ScanResult; -import android.net.wifi.SupplicantState; -import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -159,7 +156,7 @@ public class WifiWatchdogService { BLACKLISTED_AP } - WifiWatchdogService(Context context) { + public WifiWatchdogService(Context context) { mContext = context; mContentResolver = context.getContentResolver(); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); |
